<!DOCTYPE html>
<html lang="en-US" dir="ltr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>前端必备 HTTP 知识 | VitePress</title>
    <meta name="description" content="A VitePress site">
    <link rel="preload stylesheet" href="/notebook/assets/style.3dbfd0c2.css" as="style">
    
    <script type="module" src="/notebook/assets/app.8aaa4cbe.js"></script>
    <link rel="preload" href="/notebook/assets/inter-roman-latin.2ed14f66.woff2" as="font" type="font/woff2" crossorigin="">
    <link rel="modulepreload" href="/notebook/assets/chunks/framework.1336c4e5.js">
    <link rel="modulepreload" href="/notebook/assets/chunks/theme.20cddc0c.js">
    <link rel="modulepreload" href="/notebook/assets/1、学前端_5、专题篇_知识篇.md.a463ed8d.lean.js">
    <script id="check-dark-light">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
  </head>
  <body>
    <div id="app"><div class="Layout" data-v-255ec12d><!--[--><!--]--><!--[--><span tabindex="-1" data-v-ae3e3f51></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-ae3e3f51> Skip to content </a><!--]--><!----><header class="VPNav" data-v-255ec12d data-v-7e5bc4a5><div class="VPNavBar has-sidebar" data-v-7e5bc4a5 data-v-0937f67c><div class="container" data-v-0937f67c><div class="title" data-v-0937f67c><div class="VPNavBarTitle has-sidebar" data-v-0937f67c data-v-86d1bed8><a class="title" href="/notebook/" data-v-86d1bed8><!--[--><!--]--><!--[--><img class="VPImage logo" src="/notebook/Vue.png" alt data-v-8426fc1a><!--]--><!--[-->任硕的文档<!--]--><!--[--><!--]--></a></div></div><div class="content" data-v-0937f67c><div class="curtain" data-v-0937f67c></div><div class="content-body" data-v-0937f67c><!--[--><!--]--><div class="VPNavBarSearch search" style="--vp-meta-key:&#39;Meta&#39;;" data-v-0937f67c><!--[--><!----><div id="docsearch"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><svg class="DocSearch-Search-Icon" width="20" height="20" viewBox="0 0 20 20" aria-label="search icon"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"><kbd class="DocSearch-Button-Key"></kbd><kbd class="DocSearch-Button-Key">K</kbd></span></button></div><!--]--></div><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-0937f67c data-v-7f418b0f><span id="main-nav-aria-label" class="visually-hidden" data-v-7f418b0f>Main Navigation</span><!--[--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-7f418b0f data-v-a7b5672a><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-a7b5672a><span class="text" data-v-a7b5672a><!----><span data-v-a7b5672a>Java学前端</span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-a7b5672a><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-a7b5672a><div class="VPMenu" data-v-a7b5672a data-v-e7ea1737><div class="items" data-v-e7ea1737><!--[--><!--[--><div class="VPMenuGroup" data-v-e7ea1737 data-v-69e747b5><!----><!--[--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/Java%E5%AD%A6%E5%89%8D%E7%AB%AF/HTML+JS.html" data-v-2f2cfafc><!--[-->HTML+JS<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/Java%E5%AD%A6%E5%89%8D%E7%AB%AF/CSS.html" data-v-2f2cfafc><!--[-->CSS<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/Java%E5%AD%A6%E5%89%8D%E7%AB%AF/Vue2+%E7%BB%84%E4%BB%B6.html" data-v-2f2cfafc><!--[-->Vue2+组件<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/Java%E5%AD%A6%E5%89%8D%E7%AB%AF/Vue3+%E7%BB%84%E4%BB%B6.html" data-v-2f2cfafc><!--[-->Vue3+组件<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/Java%E5%AD%A6%E5%89%8D%E7%AB%AF/React.html" data-v-2f2cfafc><!--[-->React<!--]--></a></div><!--]--><!--]--></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-7f418b0f data-v-a7b5672a><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-a7b5672a><span class="text" data-v-a7b5672a><!----><span data-v-a7b5672a>软件测试</span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-a7b5672a><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-a7b5672a><div class="VPMenu" data-v-a7b5672a data-v-e7ea1737><div class="items" data-v-e7ea1737><!--[--><!--[--><div class="VPMenuGroup" data-v-e7ea1737 data-v-69e747b5><!----><!--[--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/%E6%B5%8B%E8%AF%95%E5%9F%BA%E7%A1%80.html" data-v-2f2cfafc><!--[-->测试基础<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95/%E5%8E%8B%E5%8A%9B%E6%B5%8B%E8%AF%95.html" data-v-2f2cfafc><!--[-->压力测试<!--]--></a></div><!--]--><!--]--></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-7f418b0f data-v-a7b5672a><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-a7b5672a><span class="text" data-v-a7b5672a><!----><span data-v-a7b5672a>多线程</span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-a7b5672a><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-a7b5672a><div class="VPMenu" data-v-a7b5672a data-v-e7ea1737><div class="items" data-v-e7ea1737><!--[--><!--[--><div class="VPMenuGroup" data-v-e7ea1737 data-v-69e747b5><!----><!--[--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/%E5%B9%B6%E5%8F%91%20&amp;%20%E5%A4%9A%E7%BA%BF%E7%A8%8B/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-2f2cfafc><!--[-->基础篇<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/%E5%B9%B6%E5%8F%91%20&amp;%20%E5%A4%9A%E7%BA%BF%E7%A8%8B/%E5%B9%B6%E5%8F%91%E5%AE%8C%E5%96%84.html" data-v-2f2cfafc><!--[-->进阶篇<!--]--></a></div><!--]--><!--]--></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-7f418b0f data-v-a7b5672a><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-a7b5672a><span class="text" data-v-a7b5672a><!----><span data-v-a7b5672a>开发工具</span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-a7b5672a><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-a7b5672a><div class="VPMenu" data-v-a7b5672a data-v-e7ea1737><div class="items" data-v-e7ea1737><!--[--><!--[--><div class="VPMenuGroup" data-v-e7ea1737 data-v-69e747b5><!----><!--[--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/IDEA/Chrome.html" data-v-2f2cfafc><!--[-->Chrome<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/IDEA/IDEA%E5%9F%BA%E7%A1%80.html" data-v-2f2cfafc><!--[-->IDEA基础<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/IDEA/IDEA%E6%8F%92%E4%BB%B6.html" data-v-2f2cfafc><!--[-->IDEA插件<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/IDEA/VS%20Code.html" data-v-2f2cfafc><!--[-->VS Code<!--]--></a></div><!--]--><!--]--></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-7f418b0f data-v-a7b5672a><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-a7b5672a><span class="text" data-v-a7b5672a><!----><span data-v-a7b5672a>消息中间件</span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-a7b5672a><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-a7b5672a><div class="VPMenu" data-v-a7b5672a data-v-e7ea1737><div class="items" data-v-e7ea1737><!--[--><!--[--><div class="VPMenuGroup" data-v-e7ea1737 data-v-69e747b5><!----><!--[--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6/RabbitMQ.html" data-v-2f2cfafc><!--[-->RabbitMQ<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6/RocketMQ.html" data-v-2f2cfafc><!--[-->RocketMQ<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6/Kafka.html" data-v-2f2cfafc><!--[-->Kafka<!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-69e747b5 data-v-2f2cfafc><a class="VPLink link" href="/notebook/%E6%B6%88%E6%81%AF%E4%B8%AD%E9%97%B4%E4%BB%B6/Canal.html" data-v-2f2cfafc><!--[-->Canal<!--]--></a></div><!--]--><!--]--></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--]--></nav><!----><div class="VPNavBarAppearance appearance" data-v-0937f67c data-v-f6a63727><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title="toggle dark mode" aria-checked="false" data-v-f6a63727 data-v-82b282f1 data-v-f3c41672><span class="check" data-v-f3c41672><span class="icon" data-v-f3c41672><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-82b282f1><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-82b282f1><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div><div class="VPSocialLinks VPNavBarSocialLinks social-links" data-v-0937f67c data-v-0394ad82 data-v-7bc22406><!--[--><a class="VPSocialLink no-icon" href="https://github.com/renshuo123/renshuo123.github.io" aria-label="github" target="_blank" rel="noopener" data-v-7bc22406 data-v-f80f8133><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a><a class="VPSocialLink no-icon" href="#" aria-label="twitter" target="_blank" rel="noopener" data-v-7bc22406 data-v-f80f8133><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Twitter</title><path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/></svg></a><a class="VPSocialLink no-icon" href="https://github.com/" aria-label target="_blank" rel="noopener" data-v-7bc22406 data-v-f80f8133><svg t="1676028692954" class="icon" ...</path></svg></a><!--]--></div><div class="VPFlyout VPNavBarExtra extra" data-v-0937f67c data-v-40855f84 data-v-a7b5672a><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-a7b5672a><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="icon" data-v-a7b5672a><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle><circle cx="5" cy="12" r="2"></circle></svg></button><div class="menu" data-v-a7b5672a><div class="VPMenu" data-v-a7b5672a data-v-e7ea1737><!----><!--[--><!--[--><!----><div class="group" data-v-40855f84><div class="item appearance" data-v-40855f84><p class="label" data-v-40855f84>Appearance</p><div class="appearance-action" data-v-40855f84><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title="toggle dark mode" aria-checked="false" data-v-40855f84 data-v-82b282f1 data-v-f3c41672><span class="check" data-v-f3c41672><span class="icon" data-v-f3c41672><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-82b282f1><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-82b282f1><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div></div></div><div class="group" data-v-40855f84><div class="item social-links" data-v-40855f84><div class="VPSocialLinks social-links-list" data-v-40855f84 data-v-7bc22406><!--[--><a class="VPSocialLink no-icon" href="https://github.com/renshuo123/renshuo123.github.io" aria-label="github" target="_blank" rel="noopener" data-v-7bc22406 data-v-f80f8133><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a><a class="VPSocialLink no-icon" href="#" aria-label="twitter" target="_blank" rel="noopener" data-v-7bc22406 data-v-f80f8133><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Twitter</title><path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/></svg></a><a class="VPSocialLink no-icon" href="https://github.com/" aria-label target="_blank" rel="noopener" data-v-7bc22406 data-v-f80f8133><svg t="1676028692954" class="icon" ...</path></svg></a><!--]--></div></div></div><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-0937f67c data-v-e5dd9c1c><span class="container" data-v-e5dd9c1c><span class="top" data-v-e5dd9c1c></span><span class="middle" data-v-e5dd9c1c></span><span class="bottom" data-v-e5dd9c1c></span></span></button></div></div></div></div><!----></header><div class="VPLocalNav reached-top" data-v-255ec12d data-v-5cfd5582><button class="menu" aria-expanded="false" aria-controls="VPSidebarNav" data-v-5cfd5582><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="menu-icon" data-v-5cfd5582><path d="M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"></path><path d="M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"></path><path d="M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"></path><path d="M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"></path></svg><span class="menu-text" data-v-5cfd5582>Menu</span></button><div class="VPLocalNavOutlineDropdown" style="--vp-vh:0px;" data-v-5cfd5582 data-v-18201f51><button data-v-18201f51>Return to top</button><!----></div></div><aside class="VPSidebar" data-v-255ec12d data-v-845b8fc6><div class="curtain" data-v-845b8fc6></div><nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1" data-v-845b8fc6><span class="visually-hidden" id="sidebar-aria-label" data-v-845b8fc6> Sidebar Navigation </span><!--[--><!--]--><!--[--><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>Java</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Java/Java%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Java基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Java/Java%E6%96%B0%E7%89%B9%E6%80%A7.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Java新特性</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Java/Java%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Java进阶</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Java/Java%E9%9B%86%E5%90%88.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Java集合</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Java/Java%E9%AB%98%E7%BA%A7.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Java高级</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>Linux</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Linux/Linux%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Linux基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Linux/Linux%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Linux新特性</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Linux/Shell.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Shell脚本</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Linux/%E5%AE%9E%E7%94%A8%E8%84%9A%E6%9C%AC.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>实用脚本</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Linux/%E8%BD%AF%E4%BB%B6%E9%83%A8%E7%BD%B2.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>软件部署</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>Nginx</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Nginx/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>基础篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Nginx/%E8%BF%9B%E9%98%B6%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>进阶篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Nginx/%E5%AE%9E%E6%88%98%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>实战篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Nginx/%E9%9D%A2%E8%AF%95%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>面试篇</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>SSM</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/SSM/Maven.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Maven</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/SSM/Spring.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Spring</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/SSM/SpringMVC.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>SpringMVC</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/SSM/SpringBatch.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>SpringBatch</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>SpringBoot</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/3%E3%80%81SpringBoot/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>基础篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/3%E3%80%81SpringBoot/%E5%BA%94%E7%94%A8%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>应用篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/3%E3%80%81SpringBoot/%E6%96%B0%E7%89%B9%E6%80%A7.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>新特性</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/3%E3%80%81SpringBoot/%E8%BF%90%E7%BB%B4&amp;%E5%8E%9F%E7%90%86.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>运维&原理</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>SpringCloud</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/4%E3%80%81%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>SpringCloud</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/4%E3%80%81%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%BF%85%E5%A4%87/Sentinel.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Sentinel</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>SpringSecurity</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/4%E3%80%81%E5%BE%AE%E6%9C%8D%E5%8A%A1/SpringSecurity/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>SpringSecurity基础篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/4%E3%80%81%E5%BE%AE%E6%9C%8D%E5%8A%A1/SpringSecurity/%E8%BF%9B%E9%98%B6%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>SpringSecurity进阶篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/4%E3%80%81%E5%BE%AE%E6%9C%8D%E5%8A%A1/SpringSecurity/%E9%AB%98%E7%BA%A7%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>SpringSecurity高级篇</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>Mybatis & MybatisPlus</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Mybatis&amp;MybatisPlus/Mybatis.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Mybatis</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Mybatis&amp;MybatisPlus/MybatisPlus.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>MybatisPlus</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/Mybatis&amp;MybatisPlus/JPA.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>JPA</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>Git & ChatGPT</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/5%E3%80%81%E8%BF%90%E7%BB%B4/Git.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Git</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/5%E3%80%81%E8%BF%90%E7%BB%B4/Github.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Github</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/5%E3%80%81%E8%BF%90%E7%BB%B4/ChatGPT.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>ChatGPT</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/5%E3%80%81%E8%BF%90%E7%BB%B4/Jenkins.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Jenkins</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/5%E3%80%81%E8%BF%90%E7%BB%B4/Netty.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Netty</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>数据库</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>MySQL</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/MySQL/MySQL%E6%A0%B8%E5%BF%83/%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>MySQL基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/MySQL/MySQL%E6%A0%B8%E5%BF%83/%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>MySQL进阶</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/MySQL/MySQL%E6%A0%B8%E5%BF%83/%E4%BC%98%E5%8C%96.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>MySQL优化</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/MySQL/MySQL%E6%A0%B8%E5%BF%83/%E8%AE%BE%E8%AE%A1.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>MySQL设计</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/MySQL/MySQL%E6%A0%B8%E5%BF%83/%E8%BF%90%E7%BB%B4.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>MySQL运维</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/MySQL/%E5%88%86%E5%BA%93%E5%88%86%E8%A1%A8.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>分库分表</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>Redis</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/Redis/Redis%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Redis基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/Redis/Redis%E4%BC%98%E5%8C%96.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Redis优化</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/Redis/Redis%E5%8E%9F%E7%90%86.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Redis原理</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/Redis/Redis%E9%AB%98%E7%BA%A7.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Redis高级</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/Redis/Redis%E5%AE%9E%E6%88%98.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Redis实战</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/Redis/%E6%9C%AC%E5%9C%B0%E7%BC%93%E5%AD%98.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>本地缓存</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>MongoDB</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/MongoDB/%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>MongoDB基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/MongoDB/%E6%95%B4%E5%90%88.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>MongoDB进阶</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>ElasticSearch</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/ElasticSearch/1%E3%80%81ES%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>ES基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/ElasticSearch/3%E3%80%81ES%E9%AB%98%E7%BA%A7.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>ES高级</p><!--]--></a><!----></div><!----></div><!--]--></div></section><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/influxdb.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>InfluxDB</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/2%E3%80%81%E6%95%B0%E6%8D%AE%E5%BA%93/Neo4j.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Neo4j</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>高并发 & 秒杀 & 分布式</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E4%B8%89%E9%AB%98/%E5%88%86%E5%B8%83%E5%BC%8F.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>分布式理论</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/4%E3%80%81%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%BF%85%E5%A4%87/%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>分布式锁</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E4%B8%89%E9%AB%98/%E7%A7%92%E6%9D%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>秒杀</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E4%B8%89%E9%AB%98/%E9%AB%98%E5%8F%AF%E7%94%A8.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>高可用</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E4%B8%89%E9%AB%98/%E9%AB%98%E5%B9%B6%E5%8F%91.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>高并发</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>云原生</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E4%BA%91%E5%8E%9F%E7%94%9F/Docker.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Docker</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E4%BA%91%E5%8E%9F%E7%94%9F/K8S.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>K8S</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>可视化 & 监控</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E5%8F%AF%E8%A7%86%E5%8C%96%20&amp;%20%E7%9B%91%E6%8E%A7/%E7%9B%91%E6%8E%A7%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>监控基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E5%8F%AF%E8%A7%86%E5%8C%96%20&amp;%20%E7%9B%91%E6%8E%A7/%E7%9B%91%E6%8E%A7%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>监控进阶</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E5%8F%AF%E8%A7%86%E5%8C%96%20&amp;%20%E7%9B%91%E6%8E%A7/%E5%8F%AF%E8%A7%86%E5%8C%96%E5%A4%A7%E5%B1%8F.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>可视化大屏</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E5%8F%AF%E8%A7%86%E5%8C%96%20&amp;%20%E7%9B%91%E6%8E%A7/Zabbix.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Zabbix</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>学前端</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>HTML+CSS</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/1%E3%80%81HTML+CSS/HTML%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>HTML基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/1%E3%80%81HTML+CSS/CSS%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>CSS基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/1%E3%80%81HTML+CSS/%E7%BD%91%E9%A1%B5%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>网页进阶</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>JS+TS</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/2%E3%80%81JS+TS/JS%20%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>JS基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/2%E3%80%81JS+TS/JS%20%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>JS进阶</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/2%E3%80%81JS+TS/ES6%20%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>ES6基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/2%E3%80%81JS+TS/ES6%20%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>ES6进阶</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/2%E3%80%81JS+TS/TypeScript.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>TS基础</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>NodeJS</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/4%E3%80%81Node/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Node基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/4%E3%80%81Node/%E8%BF%9B%E9%98%B6%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Node进阶</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/4%E3%80%81Node/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>项目实战</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>Vue</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/3%E3%80%81Vue/Vue3/Vue3%E8%BF%9B%E9%98%B6.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Vue3进阶</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/3%E3%80%81Vue/Vue3/Vue3%E9%AB%98%E7%BA%A7.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Vue3高级</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/3%E3%80%81Vue/Vue3/Vue3%E6%96%B0%E8%AF%AD%E6%B3%95.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>Vue3新语法</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/3%E3%80%81Vue/Vue2/Vue2%E9%A1%B9%E7%9B%AE.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>项目实战</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>小程序</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/5%E3%80%81%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>小程序基础</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/5%E3%80%81%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E4%BC%98%E5%8C%96.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>小程序优化</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/5%E3%80%81%E5%B0%8F%E7%A8%8B%E5%BA%8F/uniapp.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>uniapp</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF/5%E3%80%81%E5%B0%8F%E7%A8%8B%E5%BA%8F/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E9%A1%B9%E7%9B%AE.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>项目实战</p><!--]--></a><!----></div><!----></div><!--]--></div></section><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>计算机基础</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>数据结构</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>操作系统</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>设计模式</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>计算机网络</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/UML.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>UML</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%9F%BA%E7%A1%80/%E7%AE%97%E6%B3%95/LeetCode.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>LeetCode</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0 collapsible collapsed" data-v-845b8fc6 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h2 class="text" data-v-9b797284>项目实战</h2><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>云尚办公</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E4%BA%91%E5%B0%9A%E5%8A%9E%E5%85%AC/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>基础篇</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>小兔鲜</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E5%B0%8F%E5%85%94%E9%B2%9C/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>基础篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E5%B0%8F%E5%85%94%E9%B2%9C/%E8%BF%9B%E9%98%B6%E7%AF%871.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>进阶篇1</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E5%B0%8F%E5%85%94%E9%B2%9C/%E8%BF%9B%E9%98%B6%E7%AF%872.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>进阶篇2</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>地图</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E7%99%BE%E5%BA%A6%E5%9C%B0%E5%9B%BE/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>基础篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E7%99%BE%E5%BA%A6%E5%9C%B0%E5%9B%BE/%E8%BF%9B%E9%98%B6%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>进阶篇</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>苍穹外卖</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E8%8B%8D%E7%A9%B9%E5%A4%96%E5%8D%96/%E8%BF%9B%E9%98%B6%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>进阶篇</p><!--]--></a><!----></div><!----></div><!--]--></div></section><section class="VPSidebarItem level-1 collapsible collapsed" data-v-9b797284 data-v-9b797284><div class="item" role="button" tabindex="0" data-v-9b797284><div class="indicator" data-v-9b797284></div><h3 class="text" data-v-9b797284>黑马头条</h3><div class="caret" role="button" aria-label="toggle section" tabindex="0" data-v-9b797284><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="caret-icon" data-v-9b797284><path d="M9,19c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l5.3-5.3L8.3,6.7c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l6,6c0.4,0.4,0.4,1,0,1.4l-6,6C9.5,18.9,9.3,19,9,19z"></path></svg></div></div><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E9%BB%91%E9%A9%AC%E5%A4%B4%E6%9D%A1/%E5%9F%BA%E7%A1%80%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>基础篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E9%BB%91%E9%A9%AC%E5%A4%B4%E6%9D%A1/%E8%BF%9B%E9%98%B6%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>进阶篇</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E9%BB%91%E9%A9%AC%E5%A4%B4%E6%9D%A1/%E8%BF%9B%E9%98%B6%E7%AF%872.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>进阶篇2</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-2 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E9%BB%91%E9%A9%AC%E5%A4%B4%E6%9D%A1/%E9%AB%98%E7%BA%A7%E7%AF%87.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>高级篇</p><!--]--></a><!----></div><!----></div><!--]--></div></section><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E6%94%AF%E4%BB%98.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>支付</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/%E9%A1%B9%E7%9B%AE%E6%8E%A8%E8%8D%90.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>项目推荐</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="group" data-v-845b8fc6><section class="VPSidebarItem level-0" data-v-845b8fc6 data-v-9b797284><!----><div class="items" data-v-9b797284><!--[--><div class="VPSidebarItem level-1 is-link" data-v-9b797284 data-v-9b797284><div class="item" data-v-9b797284><div class="indicator" data-v-9b797284></div><a class="VPLink link link" href="/notebook/team.html" data-v-9b797284><!--[--><p class="text" data-v-9b797284>团队成员</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><!--]--><!--[--><!--]--></nav></aside><div class="VPContent has-sidebar" id="VPContent" data-v-255ec12d data-v-669faec9><div class="VPDoc has-sidebar has-aside" data-v-669faec9 data-v-6b87e69f><!--[--><!--]--><div class="container" data-v-6b87e69f><div class="aside" data-v-6b87e69f><div class="aside-curtain" data-v-6b87e69f></div><div class="aside-container" data-v-6b87e69f><div class="aside-content" data-v-6b87e69f><div class="VPDocAside" data-v-6b87e69f data-v-3f215769><!--[--><!--]--><!--[--><!--]--><div class="VPDocAsideOutline" data-v-3f215769 data-v-ff0f39c8><div class="content" data-v-ff0f39c8><div class="outline-marker" data-v-ff0f39c8></div><div class="outline-title" data-v-ff0f39c8>On this page</div><nav aria-labelledby="doc-outline-aria-label" data-v-ff0f39c8><span class="visually-hidden" id="doc-outline-aria-label" data-v-ff0f39c8> Table of Contents for current page </span><ul class="root" data-v-ff0f39c8 data-v-d0ee3533><!--[--><!--]--></ul></nav></div></div><!--[--><!--]--><div class="spacer" data-v-3f215769></div><!--[--><!--]--><!----><!--[--><!--]--><!--[--><!--]--></div></div></div></div><div class="content" data-v-6b87e69f><div class="content-container" data-v-6b87e69f><!--[--><!--]--><!----><main class="main" data-v-6b87e69f><div style="position:relative;" class="vp-doc _notebook_1%E3%80%81%E5%AD%A6%E5%89%8D%E7%AB%AF_5%E3%80%81%E4%B8%93%E9%A2%98%E7%AF%87_%E7%9F%A5%E8%AF%86%E7%AF%87" data-v-6b87e69f><div><h1 id="前端必备-http-知识" tabindex="-1">前端必备 HTTP 知识 <a class="header-anchor" href="#前端必备-http-知识" aria-label="Permalink to &quot;前端必备 HTTP 知识&quot;">​</a></h1><h2 id="http-起源" tabindex="-1">HTTP 起源 <a class="header-anchor" href="#http-起源" aria-label="Permalink to &quot;HTTP 起源&quot;">​</a></h2><p><code>HTTP</code> 是由蒂姆·伯纳斯-李（<code>TimBerners—Lee</code>）于1989年在欧洲核子研究组织（<code>CERN</code>）所发起</p><p>其中最著名的是 1999 年 6 月公布的 <strong>RFC 2616</strong>[1]，定义了 <code>HTTP</code> 协议中现今广泛使用的一个版本——<code>HTTP 1.1</code></p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvNoKHfCsRugWcCZBmt9sgWngfWJG6v5TQFJGNQ1RDNdacfbUM8cfyTKA/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><h2 id="http-是什么" tabindex="-1">HTTP 是什么 <a class="header-anchor" href="#http-是什么" aria-label="Permalink to &quot;HTTP 是什么&quot;">​</a></h2><p>全称：超文本传输协议（<code>HyperText Transfer Protocol</code>）</p><p>概念：<code>HTTP</code> 是一种能够获取像 <code>HTML</code>、图片等网络资源的通讯协议（<code>protocol</code>）。它是在 <code>web</code> 上进行数据交换的基础，是一种 <code>client-server</code> 协议</p><p><code>HTTP</code>——因特网的多媒体信使 ——《HTTP权威指南》。<code>HTTP</code> 在因特网的角色：充当一个信使的角色，干的就是一个跑腿的活，在客户端和服务端之间传递信息，但我们又不能缺少它。<code>HTTP</code> 协议是应用层的协议，是与前端开发最息息相关的协议。平时我们遇到的 <code>HTTP</code> 请求、 <code>HTTP</code> 缓存、<code>Cookies</code>、跨域等其实都跟 <code>HTTP</code> 息息相关</p><h2 id="http-的基础特性" tabindex="-1">HTTP 的基础特性 <a class="header-anchor" href="#http-的基础特性" aria-label="Permalink to &quot;HTTP 的基础特性&quot;">​</a></h2><ul><li>可拓展协议。<code>HTTP 1.0</code> 出现的 <code>HTTP headers</code> 让协议拓展变得更加的容易。只要服务端和客户端就 <code>headers</code> 达成语义一致，新功能就可以被轻松的加入进来</li><li><code>HTTP</code> 是无状态的、有会话的。在同一个连接中，两个执行成功的 <code>HTTP</code> 请求之间是没有关系的。这就带来了一个问题，用户没有办法在同一个网站中进行连续的交互，比如在一个电商网站里，用户把某个商品加入到购物车，切换一个页面后再次添加了商品，这两次添加商品的请求之间没有关联，浏览器无法知道用户最终选择了哪些商品。而使用 <code>HTTP</code> 的头部扩展，<code>HTTP Cookies</code> 就可以解决这个问题。把 <code>Cookies</code> 添加到头部中，创建一个会话让每次请求都能共享相同的上下文信息，达成相同的状态。</li><li><code>HTTP</code> 与连接。通过 <code>TCP</code>，或者 <code>TLS</code>——加密的 <code>TCP</code> 连接来发送，理论上任何可靠的传输协议都可以使用。连接是传输层控制的，这从根本上来讲不是 <code>HTTP</code> 的范畴。</li></ul><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.12.30/202210251051917.png" alt="image-20221025105128871" style="zoom:80%;"><p>也就是说，<code>HTTP</code> 依赖于面向连接的 <code>TCP</code> 进行消息传递，但连接并不是必须的。只需要它是可靠的，或不丢失消息的（至少返回错误）。</p><p><code>HTTP/1.0</code> 默认为每一对 <code>HTTP</code> 请求/响应都打开一个单独的 <code>TCP</code> 连接。当需要连续发起多个请求时，这种模式比多个请求共享同一个 <code>TCP</code> 链接更低效。为此，<code>HTTP 1.1</code> 持久连接的概念，底层 <code>TCP</code> 连接可以通过 <code>connection</code> 头部实现。但 <code>HTTP 1.1</code> 在连接上也是不完美的，后面我们会提到。</p><h2 id="基于-http-的组件系统" tabindex="-1">基于 HTTP 的组件系统 <a class="header-anchor" href="#基于-http-的组件系统" aria-label="Permalink to &quot;基于 HTTP 的组件系统&quot;">​</a></h2><p><code>HTTP</code> 的组件系统包括客户端、<code>web</code> 服务器和代理</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.12.30/202210251051633.png" alt="image-20221025105144597" style="zoom:80%;"><h3 id="客户端-user-agent" tabindex="-1">客户端：user-agent <a class="header-anchor" href="#客户端-user-agent" aria-label="Permalink to &quot;客户端：user-agent&quot;">​</a></h3><p>浏览器，特殊比如是工程师使用的程序，以及 <code>Web</code> 开发人员调试应用程序</p><h3 id="web服务端" tabindex="-1">Web服务端 <a class="header-anchor" href="#web服务端" aria-label="Permalink to &quot;Web服务端&quot;">​</a></h3><p>由 <code>Web Server</code> 来服务并提供客户端所请求的文档。每一个发送到服务器的请求，都会被服务器处理并返回一个消息，也就是 <code>response</code></p><h3 id="代理-proxies" tabindex="-1">代理（Proxies） <a class="header-anchor" href="#代理-proxies" aria-label="Permalink to &quot;代理（Proxies）&quot;">​</a></h3><p>在浏览器和服务器之间，有很多计算机和其他设备转发了 <code>HTTP</code> 消息。它们可能出现在传输层、网络层和物理层上，对于 <code>HTTP</code> 应用层而言就是透明的</p><p>有如下的一些作用</p><ul><li>缓存</li><li>过滤（像防病毒扫描、家长控制）</li><li>负载均衡</li><li>认证（对不同的资源进行权限控制）</li><li>日志管理</li></ul><h2 id="http-报文组成" tabindex="-1">HTTP 报文组成 <a class="header-anchor" href="#http-报文组成" aria-label="Permalink to &quot;HTTP 报文组成&quot;">​</a></h2><p>HTTP 有两种类型的消息：</p><ul><li>请求——由客户端发送用来触发一个服务器上的动作</li><li>响应——来自服务器端的应答</li></ul><p><code>HTTP</code> 消息由采用 <code>ASCII</code> 编码的多行文本构成的。在 <code>HTTP/1.1</code> 以及更早的版本中，这些消息通过连接公开的发送。在 <code>HTTP2.0</code> 中，消息被分到了多个 <code>HTTP</code> 帧中。通过配置文件（用于代理服务器或者服务器），<code>API</code>（用于浏览器）或者其他接口提供 <code>HTTP</code> 消息</p><h3 id="典型的-http-会话" tabindex="-1">典型的 HTTP 会话 <a class="header-anchor" href="#典型的-http-会话" aria-label="Permalink to &quot;典型的 HTTP 会话&quot;">​</a></h3><ul><li>建立连接 在客户端-服务器协议中，连接是由客户端发起建立的。在 <code>HTTP</code> 中打开连接意味着在底层传输层启动连接，通常是 <code>TCP</code>。使用 <code>TCP</code> 时，<code>HTTP</code> 服务器的默认端口号是 <code>80</code>，另外还有 <code>8000</code> 和 <code>8080</code> 也很常用</li><li>发送客户端请求</li><li>服务器响应请求</li></ul><h3 id="http-请求和响应" tabindex="-1">HTTP 请求和响应 <a class="header-anchor" href="#http-请求和响应" aria-label="Permalink to &quot;HTTP 请求和响应&quot;">​</a></h3><p>HTTP 请求和响应都包括起始行（<code>start line</code>）、请求头（<code>HTTP Headers</code>）、空行（<code>empty line</code>）以及 <code>body</code> 部分，如下图所示：</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvNgVcSwlONtRwsv3RVibzg9BmF7jg2VdT39ibEp0ZRAsqsCTP5BU9rHSlA/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><ul><li>起始行。请求的起始行：请求方法、请求 <code>Path</code> 和<code>HTTP</code> 版本号 响应的起始行：<code>HTTP</code> 版本号、响应状态码以及状态文本描述</li></ul><p>下面详细说下请求 <code>Path</code>，请求路径（<code>Path</code>）有以下几种：</p><p>1）一个绝对路径，末尾跟上一个 &#39; ? &#39; 和查询字符串。这是最常见的形式，称为 原始形式 (<code>origin form</code>)，被 <code>GET</code>，<code>POST</code>，<code>HEAD</code> 和 <code>OPTIONS</code> 方法所使用</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">POST / HTTP/1.1</span></span>
<span class="line"><span style="color:#A6ACCD;">GET /background.png HTTP/1.0</span></span>
<span class="line"><span style="color:#A6ACCD;">HEAD /test.html?query=alibaba HTTP/1.1</span></span>
<span class="line"><span style="color:#A6ACCD;">OPTIONS /anypage.html HTTP/1.0</span></span></code></pre></div><p>2）一个完整的 <code>URL</code>。主要在使用 <code>GET</code> 方法连接到代理的时候使用</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">GET http://developer.mozilla.org/en-US/docs/Web/HTTP/Messages HTTP/1.1</span></span></code></pre></div><p>3）由域名和可选端口（以&#39;:&#39;为前缀）组成的 <code>URL</code> 的 <code>authority component</code>，称为 <code>authority form</code>。仅在使用 <code>CONNECT</code> 建立 <code>HTTP</code> 隧道时才使用</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">CONNECT developer.mozilla.org:80 HTTP/1.1</span></span></code></pre></div><p>4）星号形式 (<code>asterisk form</code>)，一个简单的星号(&#39;*&#39;)，配合 <code>OPTIONS</code> 方法使用，代表整个服务器。</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">OPTIONS * HTTP/1.1</span></span></code></pre></div><ul><li><code>Headers</code> 请求头或者响应头。详见下面的首部。不区分大小写的字符串，紧跟着的冒号 (&#39;😂 和一个结构取决于 <code>header</code> 的值</li><li>空行。很多人容易忽略</li><li><code>Body</code></li></ul><p>请求 <code>Body</code> 部分：有些请求将数据发送到服务器以便更新数据：常见的的情况是 <code>POST</code> 请求（包含 <code>HTML</code> 表单数据）。请求报文的 <code>Body</code> 一般为两类。一类是通过 <code>Content-Type</code> 和 <code>Content-Length</code> 定义的单文件 <code>body</code>。另外一类是由多 <code>Body</code> 组成，通常是和 <code>HTML Form</code> 联系在一起的。两者的不同表现在于 <code>Content-Type</code>的值。</p><p>1）<code>Content-Type —— application/x-www-form-urlencoded</code>对于 <code>application/x-www-form-urlencoded</code> 格式的表单内容，有以下特点:</p><p>I.其中的数据会被编码成以&amp;分隔的键值对</p><p>II.字符以URL编码方式编码。</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">// 转换过程: {a: 1, b: 2} -&gt; a=1&amp;b=2 -&gt; 如下(最终形式)</span></span>
<span class="line"><span style="color:#A6ACCD;">&quot;a%3D1%26b%3D2&quot;</span></span></code></pre></div><p>2)<code>Content-Type —— multipart/form-data</code></p><p>请求头中的 <code>Content-Type</code> 字段会包含 <code>boundary</code>，且 <code>boundary</code> 的值有浏览器默认指定。例: <code>Content-Type: multipart/form-data;boundary=----WebkitFormBoundaryRRJKeWfHPGrS4LKe</code>。</p><p>数据会分为多个部分，每两个部分之间通过分隔符来分隔，每部分表述均有 <code>HTTP</code> 头部描述子包体，如<code>Content-Type</code>，在最后的分隔符会加上--表示结束。</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">Content-Disposition: form-data;name=&quot;data1&quot;;</span></span>
<span class="line"><span style="color:#A6ACCD;">Content-Type: text/plain</span></span>
<span class="line"><span style="color:#A6ACCD;">data1</span></span>
<span class="line"><span style="color:#A6ACCD;">----WebkitFormBoundaryRRJKeWfHPGrS4LKe</span></span>
<span class="line"><span style="color:#A6ACCD;">Content-Disposition: form-data;name=&quot;data2&quot;;</span></span>
<span class="line"><span style="color:#A6ACCD;">Content-Type: text/plain</span></span>
<span class="line"><span style="color:#A6ACCD;">data2</span></span>
<span class="line"><span style="color:#A6ACCD;">----WebkitFormBoundaryRRJKeWfHPGrS4LKe--</span></span></code></pre></div><p>响应 <code>Body</code> 部分：</p><p>1）由已知长度的单个文件组成。该类型 <code>body</code> 由两个 <code>header</code> 定义：<code>Content-Type</code> 和 <code>Content-Length</code></p><p>2）由未知长度的单个文件组成，通过将 <code>Transfer-Encoding</code> 设置为 <code>chunked</code> 来使用 <code>chunks</code> 编码。</p><p>关于 <code>Content-Length</code> 在下面 <code>HTTP 1.0</code> 中会提到，这个是 <code>HTTP 1.0</code> 中新增的非常重要的头部。</p><h3 id="方法" tabindex="-1">方法 <a class="header-anchor" href="#方法" aria-label="Permalink to &quot;方法&quot;">​</a></h3><p>安全方法：<code>HTTP</code> 定义了一组被称为安全方法的方法。<code>GET</code> 方法和 <code>HEAD</code> 方法都被认为是安全的，这意味着 <code>GET</code> 方法和 <code>HEAD</code> 方法都不会产生什么动作 —— <code>HTTP</code> 请求不会再服务端产生什么结果，但这并不意味着什么动作都没发生，其实这更多的是 <code>web</code> 开发者决定的</p><ul><li><code>GET</code>：请求服务器发送某个资源</li><li><code>HEAD</code>：跟 <code>GET</code> 方法类似，但服务器在响应中只返回了首部。不会返回实体的主体部分。</li><li><code>PUT</code>：向服务器中写入文档。语义：用请求的主体部分来创建一个由所请求的 <code>URL</code> 命名的新文档</li><li><code>POST</code>：用来向服务器中输入数据的。通常我们提交表单数据给服务器。【<code>POST</code> 用于向服务器发送数据，<code>PUT</code> 方法用于向服务器上的资源（例如文件）中存储数据】</li><li><code>TRACE</code>：主要用于诊断。实现沿通向目标资源的路径的消息环回（<code>loop-back</code>）测试 ，提供了一种实用的 <code>debug</code> 机制。</li><li><code>OPTIONS</code>：请求 <code>WEB</code> 服务器告知其支持的各种功能。可以询问服务器支持哪些方法。或者针对某些特殊资源支持哪些方法。</li><li><code>DELETE</code>：请求服务器删除请求 <code>URL</code> 中指定的的资源</li></ul><h3 id="get-和-post-的区别" tabindex="-1">GET 和 POST 的区别 <a class="header-anchor" href="#get-和-post-的区别" aria-label="Permalink to &quot;GET 和 POST 的区别&quot;">​</a></h3><p>首先要了解下副作用和幂等的概念，副作用指的是对服务器端资源做修改。幂等指发送 <code>M</code> 和 <code>N</code> 次请求（两者不相同且都大于 1），服务器上资源的状态一致。应用场景上，get是无副作用的，幂等的。post 主要是有副作用的，不幂等的情况</p><p>技术上有以下的区分：</p><ul><li>缓存：<code>Get</code> 请求能缓存，<code>Post</code> 请求不能</li><li>安全：<code>Get</code> 请求没有 <code>Post</code> 请求那么安全，因为请求都在 <code>URL</code> 中。且会被浏览器保存历史纪录。<code>POST</code> 放在请求体中，更加安全</li><li>限制：<code>URL</code> 有长度限制，会干预 <code>Get</code> 请求，这个是浏览器决定的</li><li>编码：<code>GET</code> 请求只能进行 <code>URL</code> 编码，只能接收 <code>ASCII</code> 字符，而 <code>POST</code> 没有限制。<code>POST</code> 支持更多的编码类型，而且不对数据类型做限制</li><li>从 <code>TCP</code> 的角度，<code>GET</code> 请求会把请求报文一次性发出去，而 <code>POST</code> 会分为两个 <code>TCP</code> 数据包，首先发 <code>header</code> 部分，如果服务器响应 <code>100(continue)</code>， 然后发 <code>body</code> 部分。(火狐浏览器除外，它的 <code>POST</code> 请求只发一个 <code>TCP</code> 包)</li></ul><h3 id="状态码" tabindex="-1">状态码 <a class="header-anchor" href="#状态码" aria-label="Permalink to &quot;状态码&quot;">​</a></h3><ul><li><p>100~199——信息性状态码</p><p>101 Switching Protocols。在HTTP升级为WebSocket的时候，如果服务器同意变更，就会发送状态码 101。</p></li><li><p>200~299——成功状态码</p><p>200 OK，表示从客户端发来的请求在服务器端被正确处理</p><p>204 No content，表示请求成功，但响应报文不含实体的主体部分</p><p>205 Reset Content，表示请求成功，但响应报文不含实体的主体部分，但是与 204 响应不同在于要求请求方重置内容</p><p>206 Partial Content，进行范围请求</p></li><li><p>300~399——重定向状态码</p><p>301 moved permanently，永久性重定向，表示资源已被分配了新的 URL</p><p>302 found，临时性重定向，表示资源临时被分配了新的 URL</p><p>303 see other，表示资源存在着另一个 URL，应使用 GET 方法获取资源</p><p>304 not modified，表示服务器允许访问资源，但因发生请求未满足条件的情况</p><p>307 temporary redirect，临时重定向，和302含义类似，但是期望客户端保持请求方法不变向新的地址发出请求</p></li><li><p>400~499——客户端错误状态码</p><p>400 bad request，请求报文存在语法错误</p><p>401 unauthorized，表示发送的请求需要有通过 HTTP 认证的认证信息</p><p>403 forbidden，表示对请求资源的访问被服务器拒绝</p><p>404 not found，表示在服务器上没有找到请求的资源</p></li><li><p>500~599——服务器错误状态码</p><p>500 internal sever error，表示服务器端在执行请求时发生了错误</p><p>501 Not Implemented，表示服务器不支持当前请求所需要的某个功能</p><p>503 service unavailable，表明服务器暂时处于超负载或正在停机维护，无法处理请求</p></li></ul><h3 id="首部" tabindex="-1">首部 <a class="header-anchor" href="#首部" aria-label="Permalink to &quot;首部&quot;">​</a></h3><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">HTTP Headers</span></span></code></pre></div><p>1.通用首部（<code>General headers</code>）同时适用于请求和响应消息，但与最终消息主体中传输的数据无关的消息头。如 <code>Date</code></p><p>2.请求首部（<code>Request headers</code>）包含更多有关要获取的资源或客户端本身信息的消息头。如 User-Agent</p><p>3.响应首部（<code>Response headers</code>）包含有关响应的补充信息</p><p>4.实体首部（<code>Entity headers</code>）含有关实体主体的更多信息，比如主体长(<code>Content-Length</code>)度或其 <code>MIME</code> 类型。如 <code>Accept-Ranges</code></p><p>详细的 <code>Header</code> 见 <strong>HTTP Headers 集合</strong>[2]</p><h2 id="http-的前世今生" tabindex="-1">HTTP 的前世今生 <a class="header-anchor" href="#http-的前世今生" aria-label="Permalink to &quot;HTTP 的前世今生&quot;">​</a></h2><p><code>HTTP（HyperText Transfer Protocol）</code>是万维网（<code>World Wide Web</code>）的基础协议。<code>Tim Berners-Lee</code> 博士和他的团队在<code>1989-1991</code>年间创造出它。【HTTP、网络浏览器、服务器】</p><p>在 1991 年发布了 <code>HTTP 0.9</code> 版，在 1996 年发布 1.0 版，1997 年是 1.1 版，1.1 版也是到今天为止传输最广泛的版本。2015 年发布了 2.0 版，其极大的优化了 <code>HTTP/1.1</code> 的性能和安全性，而 2018 年发布的 3.0 版，继续优化 <code>HTTP/2</code>，激进地使用 <code>UDP</code> 取代 <code>TCP</code> 协议，目前，<code>HTTP/3</code> 在 2019 年 9 月 26 日 被 <code>Chrome</code>，<code>Firefox</code>，和 <code>Cloudflare</code> 支持</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvNxKRINPCaFYRXHVXO7ibv21VJjwruiczoO8nQwxqptheQSkDhDUC9n7IQ/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><h3 id="http-0-9" tabindex="-1">HTTP 0.9 <a class="header-anchor" href="#http-0-9" aria-label="Permalink to &quot;HTTP 0.9&quot;">​</a></h3><p>单行协议，请求由单行指令构成。以唯一可用的方法 <code>GET</code> 开头。后面跟的是目标资源的路径</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">GET /mypage.html</span></span></code></pre></div><p>响应：只包括响应文档本身</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">&lt;HTML&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">这是一个非常简单的HTML页面</span></span>
<span class="line"><span style="color:#A6ACCD;">&lt;/HTML&gt;</span></span></code></pre></div><ul><li>没有响应头，只传输 <code>HTML</code> 文件</li><li>没有状态码</li></ul><h3 id="http-1-0" tabindex="-1">HTTP 1.0 <a class="header-anchor" href="#http-1-0" aria-label="Permalink to &quot;HTTP 1.0&quot;">​</a></h3><p><strong>RFC 1945</strong>[3] 提出了 <code>HTTP1.0</code>，<strong>构建更好可拓展性</strong></p><ul><li>协议版本信息会随着每个请求发送</li><li>响应状态码</li><li>引入了 <code>HTTP</code> 头的概念，无论是请求还是拓展，允许传输元数据。使协议变得灵活，更加具有拓展性</li><li><code>Content-Type</code> 请求头，具备了传输除纯文本 <code>HTML</code> 文件以外其他类型文档的能力 在响应中，<code>Content-Type</code> 标头告诉客户端实际返回的内容的内容类型</li></ul><p>媒体类型是一种标准。用来表示文档、文件或者字节流的性质和格式。浏览器通常使用 <code>MIME</code> （<code>Multipurpose Internet Mail Extensions</code> ）类型来确定如何处理 <code>URL</code>，因此 <code>Web</code> 服务器在响应头中配置正确的 <code>MIME</code> 类型会非常的重要。如果配置不正确，可能会导致网站无法正常的工作。<code>MIME</code> 的组成结构非常简单；由类型与子类型两个字符串中间用&#39;/&#39;分隔而组成。</p><p><code>HTTP</code> 从 <code>MIME type</code> 取了一部分来标记报文 <code>body</code> 部分的数据类型，这些类型体现在<code>Content-Type</code> 这个字段，当然这是针对于发送端而言，接收端想要收到特定类型的数据，也可以用 <code>Accept</code> 字段。</p><p>这两个字段的取值可以分为下面几类:</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">- text：text/html, text/plain, text/css 等</span></span>
<span class="line"><span style="color:#A6ACCD;">- image: image/gif, image/jpeg, image/png 等</span></span>
<span class="line"><span style="color:#A6ACCD;">- audio/video: audio/mpeg, video/mp4 等</span></span>
<span class="line"><span style="color:#A6ACCD;">- application: application/json, application/javascript, application/pdf, application/octet-stream</span></span></code></pre></div><p>同时为了约定请求的数据和响应数据的压缩方式、支持语言、字符集等，还提出了以下的 <code>Header</code></p><p>1.压缩方式:发送端：<code>Content-Encoding</code>（服务端告知客户端，服务器对实体的主体部分的编码方式） 和 接收端：<code>Accept-Encoding</code>（用户代理支持的编码方式），值有 gzip: 当今最流行的压缩格式；deflate: 另外一种著名的压缩格式；br: 一种专门为 HTTP 发明的压缩算法</p><p>2.支持语言：<code>Content-Language</code> 和 <code>Accept-Language</code>（用户代理支持的自然语言集）</p><p>3.字符集：发送端：<code>Content-Type</code> 中，以 <code>charset</code> 属性指定。接收端：<code>Accept-Charset</code>（用户代理支持的字符集）。</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">// 发送端</span></span>
<span class="line"><span style="color:#A6ACCD;">Content-Encoding: gzip</span></span>
<span class="line"><span style="color:#A6ACCD;">Content-Language: zh-CN, zh, en</span></span>
<span class="line"><span style="color:#A6ACCD;">Content-Type: text/html; charset=utf-8</span></span>
<span class="line"><span style="color:#A6ACCD;"></span></span>
<span class="line"><span style="color:#A6ACCD;">// 接收端</span></span>
<span class="line"><span style="color:#A6ACCD;">Accept-Encoding: gzip</span></span>
<span class="line"><span style="color:#A6ACCD;">Accept-Language: zh-CN, zh, en</span></span>
<span class="line"><span style="color:#A6ACCD;">Accept-Charset: charset=utf-8</span></span></code></pre></div><p>虽然 <code>HTTP1.0</code> 在 <code>HTTP 0.9</code> 的基础上改进了很多，但还是存在这不少的缺点</p><p><code>HTTP/1.0</code> 版的主要缺点是，每个 <code>TCP</code> 连接只能发送一个请求。发送数据完毕，连接就关闭，如果还要请求其他资源，就必须再新建一个连接。<code>TCP</code> 连接的新建成本很高，因为需要客户端和服务器三次握手，并且开始时发送速率较慢（<code>slow start</code>）。</p><p><code>HTTP</code> 最早期的模型，也是 <code>HTTP/1.0</code> 的默认模型，是短连接。每一个 <code>HTTP</code> 请求都由它自己独立的连接完成；这意味着发起每一个 <code>HTTP</code> 请求之前都会有一次 <code>TCP</code> 握手，而且是连续不断的。</p><h3 id="http-1-1" tabindex="-1">HTTP 1.1 <a class="header-anchor" href="#http-1-1" aria-label="Permalink to &quot;HTTP 1.1&quot;">​</a></h3><p><code>HTTP/1.1</code> 在1997年1月以 <strong>RFC 2068</strong>[4] 文件发布。</p><p><code>HTTP 1.1</code> 消除了大量歧义内容并引入了多项技术</p><ul><li>连接可以复用。长连接：<code>connection: keep-alive</code>。<code>HTTP 1.1</code> 支持长连接（<code>PersistentConnection</code>），在一个 <code>TCP</code> 连接上可以传送多个 <code>HTTP</code> 请求和响应，减少了建立和关闭连接的消耗和延迟，在 <code>HTTP1.1</code> 中默认开启 <code>Connection：keep-alive</code>，一定程度上弥补了 <code>HTTP1.0</code> 每次请求都要创建连接的缺点。</li><li>增加了管道化技术（<code>HTTP Pipelinling</code>），允许在第一个应答被完全发送完成之前就发送第二个请求，以降低通信延迟。复用同一个 <code>TCP</code> 连接期间，即便是通过管道同时发送了多个请求，服务端也是按请求的顺序依次给出响应的；而客户端在未收到之前所发出所有请求的响应之前，将会阻塞后面的请求(排队等待)，这称为&quot;队头堵塞&quot;（<code>Head-of-line blocking</code>）。</li><li>支持响应分块，分块编码传输：<code>Transfer-Encoding: chunked``Content-length</code> 声明本次响应的数据长度。<code>keep-alive</code> 连接可以先后传送多个响应，因此用 <code>Content-length</code> 来区分数据包是属于哪一个响应。使用 <code>Content-Length</code> 字段的前提条件是，服务器发送响应之前，必须知道响应的数据长度。对于一些很耗时的动态操作来说，这意味着，服务器要等到所有操作完成，才能发送数据，显然这样的效率不高。更好的处理方法是，产生一块数据，就发送一块，采用&quot;流模式&quot;（<code>Stream</code>）取代&quot;缓存模式&quot;（<code>Buffer</code>）。因此，<code>HTTP 1.1</code> 规定可以不使用 <code>Content-Length</code> 字段，而使用&quot;分块传输编码&quot;（<code>Chunked Transfer Encoding</code>）。只要请求或响应的头信息有 <code>Transfer-Encoding: chunked</code> 字段，就表明 <code>body</code> 将可能由数量未定的多个数据块组成。每个数据块之前会有一行包含一个 16 进制数值，表示这个块的长度；最后一个大小为 0 的块，就表示本次响应的数据发送完了。</li><li>引入额外的缓存控制机制。在 <code>HTTP1.0</code> 中主要使用 <code>header</code> 里的 <code>If-Modified-Since</code>,<code>Expires</code> 等来做为缓存判断的标准，<code>HTTP1.1</code> 则引入了更多的缓存控制策略例如 <code>Entity tag</code>, <code>If-None-Match</code>，<code>Cache-Control</code> 等更多可供选择的缓存头来控制缓存策略。</li><li><code>Host</code> 头。不同的域名配置同一个 <code>IP</code> 地址的服务器。<code>Host</code> 是 <code>HTTP 1.1</code> 协议中新增的一个请求头，主要用来实现虚拟主机技术。</li></ul><p>虚拟主机（<code>virtual hosting</code>）即共享主机（<code>shared web hosting</code>），可以利用虚拟技术把一台完整的服务器分成若干个主机，因此可以在单一主机上运行多个网站或服务。</p><p>举个栗子，有一台 <code>ip</code> 地址为 <code>61.135.169.125</code> 的服务器，在这台服务器上部署着谷歌、百度、淘宝的网站。为什么我们访问 <code>https://www.google.com</code> 时，看到的是 <code>Google</code> 的首页而不是百度或者淘宝的首页？原因就是 <code>Host</code> 请求头决定着访问哪个虚拟主机。</p><h3 id="http-2-0" tabindex="-1">HTTP 2.0 <a class="header-anchor" href="#http-2-0" aria-label="Permalink to &quot;HTTP 2.0&quot;">​</a></h3><p>2015年，<code>HTTP2.0</code> 面世。<strong>rfc7540</strong>[5]</p><ul><li><p><code>HTTP/2</code> 是二进制协议而不是文本协议。先来看几个概念：</p></li><li><ul><li>帧：客户端与服务器通过交换帧来通信，帧是基于这个新协议通信的最小单位。</li><li>消息：是指逻辑上的 HTTP 消息，比如请求、响应等，由一或多个帧组成。</li><li>流：流是连接中的一个虚拟信道，可以承载双向的消息；每个流都有一个唯一的整数标识符</li></ul></li></ul><p><code>HTTP 2.0</code> 中的帧将 <code>HTTP/1.x</code> 消息分成帧并嵌入到流 (<code>stream</code>) 中。数据帧和报头帧分离，这将允许报头压缩。将多个流组合，这是一个被称为多路复用 (<code>multiplexing</code>) 的过程，它允许更有效的底层 <code>TCP</code> 连接。</p><p>也就是说，流用来承载消息，消息又是有一个或多个帧组成。二进制传输的方式更加提升了传输性能。每个数据流都以消息的形式发送，而消息又由一个或多个帧组成。帧是流中的数据单位。</p><p><code>HTTP</code> 帧现在对 <code>Web</code> 开发人员是透明的。在 <code>HTTP/2</code> 中，这是一个在 <code>HTTP/1.1</code> 和底层传输协议之间附加的步骤。<code>Web</code> 开发人员不需要在其使用的 <code>API</code> 中做任何更改来利用 <code>HTTP</code> 帧；当浏览器和服务器都可用时，<code>HTTP/2</code> 将被打开并使用。</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvNMmtnuGp9WEhPwEkyR5aDKe6TeyzJmMF3v5B6KiaY6Vumw2zVJicvl6ibg/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><ul><li>这是一个复用协议。并行的请求能在同一个连接中处理，移除了 <code>HTTP/1.x</code> 中顺序和阻塞的约束。多路复用允许同时通过单一的 <code>HTTP/2</code> 连接发起多重的请求-响应消息</li></ul><p>之前我们提到，虽然 <code>HTTP 1.1</code> 有了长连接和管道化的技术，但是还是会存在 队头阻塞。而 <code>HTTP 2.0</code> 就解决了这个问题<code>HTTP/2</code> 中新的二进制分帧层突破了这些限制，实现了完整的请求和响应复用：客户端和服务器可以将 <code>HTTP</code> 消息分解为互不依赖的帧，然后交错发送，最后再在另一端把它们重新组装起来。</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvN40MZ3yThKr1UPgOojc2ZTXcWUBor3icxCBc3biaZg8L5hMicJ9yYlA8pg/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>如上图所示，快照捕捉了同一个连接内并行的多个数据流。客户端正在向服务器传输一个 <code>DATA</code> 帧（数据流 5），与此同时，服务器正向客户端交错发送数据流 1 和数据流 3 的一系列帧。因此，一个连接上同时有三个并行数据流。</p><p>将 HTTP 消息分解为独立的帧，交错发送，然后在另一端重新组装是 <code>HTTP 2</code> 最重要的一项增强。事实上，这个机制会在整个网络技术栈中引发一系列连锁反应，从而带来巨大的性能提升，让我们可以：1.并行交错地发送多个请求，请求之间互不影响。2.并行交错地发送多个响应，响应之间互不干扰。3.使用一个连接并行发送多个请求和响应。4.消除不必要的延迟和提高现有网络容量的利用率，从而减少页面加载时间。5.不必再为绕过 HTTP/1.x 限制而做很多工作(比如精灵图) ...</p><p>连接共享，即每一个 <code>request</code> 都是是用作连接共享机制的。一个 <code>request</code> 对应一个 <code>id</code>，这样一个连接上可以有多个 <code>request</code>，每个连接的 <code>request</code> 可以随机的混杂在一起，接收方可以根据 <code>request</code> 的 <code>id</code> 将 <code>request</code> 再归属到各自不同的服务端请求里面。</p><p><code>HTTP 1.1</code> 和 <code>HTTP 2.0</code> 的对比，可以参考这个 <strong>网站 demo 演示</strong>[6]</p><p><code>HTTP 1.1</code> 演示如下：<img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvNb1ERhCvQicPiaSPL8D6bZnDblDnds2hEdBmQEIiae6DF0qK0w6HFzI11A/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p><code>HTTP2.0</code> 演示如下：</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvNHic2cibZbaJWMO54Gguyds8rFtAlDvUVmwLYXyjNIjBVBiboicttoqUMibg/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvNtOp2wyzLZuQPgSAWMianTQpFZjL06GEzqy3mIy16VsSrxatPWPu9Neg/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><ul><li>压缩了<code>headers</code>。<code>HTTP1.x</code> 的 <code>header</code> 带有大量信息，而且每次都要重复发送，就造成了性能的损耗。为了减少此开销和提升性能，<code>HTTP/2</code> 使用 <code>HPACK</code> 压缩格式压缩请求和响应标头元数据，这种格式采用两种简单但是强大的技术：这种格式支持通过静态霍夫曼代码对传输的标头字段进行编码，从而减小了各个传输的大小。这种格式要求客户端和服务器同时维护和更新一个包含之前见过的标头字段的索引列表（换句话说，它可以建立一个共享的压缩上下文），此列表随后会用作参考，对之前传输的值进行有效编码。</li></ul><p><img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvNicZbm31mVLbTvZTrT0XhlTKFTWgmDFhFe8Qicbneiby8DLEjL8oCe87Yg/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><ul><li>服务端推送。其允许服务器在客户端缓存中填充数据，通过一个叫服务器推送的机制来提前请求。服务器向客户端推送资源无需客户端明确地请求，服务端可以提前给客户端推送必要的资源，这样可以减少请求延迟时间，例如服务端可以主动把 <code>JS</code> 和 <code>CSS</code> 文件推送给客户端，而不是等到 <code>HTML</code> 解析到资源时发送请求，这样可以减少延迟时间大致过程如下图所示：</li></ul><p><img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvN8GKs6xx8gDib3gxlsumSqtQr8u9xwOvCpT2TNOdKwiaWuqOHgfQ2bmTA/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><h3 id="如何升级你的-http-版本" tabindex="-1">如何升级你的 HTTP 版本 <a class="header-anchor" href="#如何升级你的-http-版本" aria-label="Permalink to &quot;如何升级你的 HTTP 版本&quot;">​</a></h3><p>使用 <code>HTTP/1.1</code> 和 <code>HTTP/2</code> 对于站点和应用来说是透明的。拥有一个最新的服务器和新点的浏览器进行交互就足够了。只有一小部分群体需要做出改变，而且随着陈旧的浏览器和服务器的更新，而不需 <code>Web</code> 开发者做什么，用的人自然就增加了</p><h2 id="https" tabindex="-1">HTTPS <a class="header-anchor" href="#https" aria-label="Permalink to &quot;HTTPS&quot;">​</a></h2><p><code>HTTPS</code> 也是通过 <code>HTTP</code> 协议进行传输信息，但是采用了 <code>TLS</code> 协议进行了加密</p><h3 id="对称加密和非对称加密" tabindex="-1">对称加密和非对称加密 <a class="header-anchor" href="#对称加密和非对称加密" aria-label="Permalink to &quot;对称加密和非对称加密&quot;">​</a></h3><blockquote><p>对称加密就是两边拥有相同的秘钥，两边都知道如何将密文加密解密。但是因为传输数据都是走的网络，如果将秘钥通过网络的方式传递的话，一旦秘钥被截获就没有加密的意义的</p></blockquote><blockquote><p>非对称加密：公钥大家都知道，可以用公钥加密数据。但解密数据必须使用私钥，私钥掌握在颁发公钥的一方。首先服务端将公钥发布出去，那么客户端是知道公钥的。然后客户端创建一个秘钥，并使用公钥加密，发送给服务端。服务端接收到密文以后通过私钥解密出正确的秘钥</p></blockquote><h3 id="tls-握手过程" tabindex="-1">TLS 握手过程 <a class="header-anchor" href="#tls-握手过程" aria-label="Permalink to &quot;TLS 握手过程&quot;">​</a></h3><p><code>TLS</code> 握手的过程采用的是非对称加密</p><ul><li><code>Client Hello</code>: 客户端发送一个随机值(<code>Random1</code>)以及需要的协议和加密方式。</li><li><code>Server Hello</code> 以及 <code>Certificate</code>: 服务端收到客户端的随机值，自己也产生一个随机值(<code>Random2</code>)，并根据客户端需求的协议和加密方式来使用对应的方式，并且发送自己的证书（如果需要验证客户端证书需要说明）</li><li><code>Certificate Verify</code>: 客户端收到服务端的证书并验证是否有效，验证通过会再生成一个随机值(<code>Random3</code>)，通过服务端证书的公钥去加密这个随机值并发送给服务端，如果服务端需要验证客户端证书的话会附带证书</li><li><code>Server 生成 secret</code>: 服务端收到加密过的随机值并使用私钥解密获得第三个随机值(<code>Random3</code>)，这时候两端都拥有了三个随机值，可以通过这三个随机值按照之前约定的加密方式生成密钥，接下来的通信就可以通过该密钥来加密解密</li></ul><h2 id="http-缓存" tabindex="-1">HTTP 缓存 <a class="header-anchor" href="#http-缓存" aria-label="Permalink to &quot;HTTP 缓存&quot;">​</a></h2><h3 id="强缓存" tabindex="-1">强缓存 <a class="header-anchor" href="#强缓存" aria-label="Permalink to &quot;强缓存&quot;">​</a></h3><p>强缓存主要是由 <code>Cache-control</code> 和 <code>Expires</code> 两个 <code>Header</code> 决定的</p><p><code>Expires</code> 的值和头里面的 <code>Date</code> 属性的值来判断是否缓存还有效。<code>Expires</code> 是 <code>Web</code> 服务器响应消息头字段，在响应 <code>http</code> 请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据，而无需再次请求。<code>Expires</code> 的一个缺点就是，返回的到期时间是服务器端的时间，这是一个绝对的时间，这样存在一个问题，如果客户端的时间与服务器的时间相差很大（比如时钟不同步，或者跨时区），那么误差就很大。</p><p><code>Cache-Control</code> 指明当前资源的有效期，控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。但是其设置的是一个相对时间。</p><p>指定过期时间：<code>max-age</code> 是距离请求发起的时间的秒数，比如下面指的是距离发起请求 31536000S 内都可以命中强缓存</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">Cache-Control: max-age=31536000</span></span></code></pre></div><p>表示没有缓存</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">Cache-Control: no-store</span></span></code></pre></div><p>有缓存但要重新验证</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">Cache-Control: no-cache</span></span></code></pre></div><p>私有和公共缓存</p><p><code>public</code> 表示响应可以被任何中间人（比如中间代理、<code>CDN</code> 等缓存） 而 <code>private</code> 则表示该响应是专用于某单个用户的，中间人不能缓存此响应，该响应只能应用于浏览器私有缓存中。</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">Cache-Control: private</span></span>
<span class="line"><span style="color:#A6ACCD;">Cache-Control: public</span></span></code></pre></div><p>验证方式：以下表示一旦资源过期（比如已经超过 <code>max-age</code>），在成功向原始服务器验证之前，缓存不能用该资源响应后续请求</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">Cache-Control: must-revalidate</span></span></code></pre></div><p><code>Cache-control</code> 优先级比 <code>Expires</code> 优先级高</p><p>以下是一个 <code>Cache-Control</code> 强缓存的过程：</p><ul><li>首次请求，直接从 server 中获取。其中会设置 <code>max-age=100</code></li><li>第二次请求，<code>age=10</code>，小于 100，则命中 <code>Cache</code>，直接返回</li><li>第三次请求，<code>age=110</code>，大于 110。强缓存失效，就需要再次请求 <code>Server</code></li></ul><img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvN7PwDYajlYQsy8kAzqtEQac5eu7NtGpAGvL4kCEROQuyU34ryhVvoNw/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片" style="zoom:80%;"><h3 id="协商缓存" tabindex="-1">协商缓存 <a class="header-anchor" href="#协商缓存" aria-label="Permalink to &quot;协商缓存&quot;">​</a></h3><ul><li><code>If-Modified-Since——Last-Modified</code></li></ul><p><code>Last-Modified</code> 表示本地文件最后修改日期，浏览器会在 <code>request header</code> 加上 <code>If-Modified-Since</code>（上次返回的 <code>Last-Modified</code> 的值），询问服务器在该日期后资源是否有更新，有更新的话就会将新的资源发送回来</p><p>但是如果在本地打开缓存文件，就会造成 <code>Last-Modified</code> 被修改，所以在 <code>HTTP / 1.1</code> 出现了 <code>ETag</code></p><ul><li><code>If-none-match——ETags</code></li></ul><p><code>Etag</code> 就像一个指纹，资源变化都会导致 <code>ETag</code> 变化，跟最后修改时间没有关系，<code>ETag</code> 可以保证每一个资源是唯一的。<code>If-None-Match</code> 的 <code>header</code> 会将上次返回的 <code>Etag</code> 发送给服务器，询问该资源的 <code>Etag</code> 是否有更新，有变动就会发送新的资源回来</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">If-none-match`、`ETags` 优先级高于 `If-Modified-Since、Last-Modified</span></span></code></pre></div><p>第一次请求：</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvNKd9HCOXvg9evnZ8Via0v3j9cEeaauXuj2Zyic9uSds4diavSXarAVCO9g/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>第二次请求相同网页：</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvNDw5BPliaicNNulJDzMINsS4vIUeZuCJ7nGcCfOIXcC96ECk3V70Zmp7A/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>协商缓存，假如没有改动的话，返回 304 ，改动了返回 200 资源</p><ul><li>200：强缓存 <code>Expires/Cache-Control</code> 失效时，返回新的资源文件</li><li>200 <code>(from cache)</code>: 强缓 <code>Expires/Cache-Control</code> 两者都存在，未过期，<code>Cache-Control</code> 优先 <code>Expires</code> 时，浏览器从本地获取资源成功</li><li>304 <code>(Not Modified)</code>：协商缓存 <code>Last-modified/Etag</code> 没有过期时，服务端返回状态码304</li></ul><p>现在的200<code>(from cache)</code>已经变成了 <code>disk cache</code>(磁盘缓存)和 <code>memory cache</code>(内存缓存)两种</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvNviccmhz1NGPpqCcyVG9NeibNSQOibSZfrkbYQZr6TU1iarHXicUSxeVSFaw/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><h3 id="revving-技术" tabindex="-1">revving 技术 <a class="header-anchor" href="#revving-技术" aria-label="Permalink to &quot;revving 技术&quot;">​</a></h3><p>上面提到 <code>HTTP</code> 缓存相关，但是很多有时候，我们希望上线之后需要更新线上资源。</p><p><code>web</code> 开发者发明了一种被 <code>Steve Souders</code> 称之为 <code>revving</code> 的技术。不频繁更新的文件会使用特定的命名方式：在 <code>URL</code> 后面（通常是文件名后面）会加上版本号。</p><p>弊端：更新了版本号，所有引用这些的资源的地方的版本号都要改变</p><p><code>web</code> 开发者们通常会采用自动化构建工具在实际工作中完成这些琐碎的工作。当低频更新的资源（<code>js/css</code>）变动了，只用在高频变动的资源文件（<code>html</code>）里做入口的改动。</p><h2 id="cookies" tabindex="-1">Cookies <a class="header-anchor" href="#cookies" aria-label="Permalink to &quot;Cookies&quot;">​</a></h2><p><code>HTTP Cookie</code>（也叫 <code>Web Cookie</code> 或浏览器 <code>Cookie</code>）是服务器发送到用户浏览器并保存在本地的一小块数据，它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。</p><h3 id="创建-cookie" tabindex="-1">创建 cookie <a class="header-anchor" href="#创建-cookie" aria-label="Permalink to &quot;创建 cookie&quot;">​</a></h3><p><code>Set-Cookie</code> 响应头部和 <code>Cookie</code> 请求头部</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">Set-Cookie: &lt;cookie名&gt;=&lt;cookie值&gt;</span></span></code></pre></div><h3 id="会话期cookie" tabindex="-1">会话期Cookie <a class="header-anchor" href="#会话期cookie" aria-label="Permalink to &quot;会话期Cookie&quot;">​</a></h3><p>会话期Cookie是最简单的 <code>Cookie</code>：浏览器关闭之后它会被自动删除，也就是说它仅在会话期内有效。会话期 <code>Cookie</code> 不需要指定过期时间（<code>Expires</code>）或者有效期（<code>Max-Age</code>）。需要注意的是，有些浏览器提供了会话恢复功能，这种情况下即使关闭了浏览器，会话期 <code>Cookie</code> 也会被保留下来，就好像浏览器从来没有关闭一样</p><h3 id="持久性cookie" tabindex="-1">持久性Cookie <a class="header-anchor" href="#持久性cookie" aria-label="Permalink to &quot;持久性Cookie&quot;">​</a></h3><p>和关闭浏览器便失效的会话期 <code>Cookie</code> 不同，持久性 <code>Cookie</code> 可以指定一个特定的过期时间（<code>Expires</code>）或有效期（<code>Max-Age</code>）。</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;</span></span></code></pre></div><h3 id="cookie的secure和httponly-标记" tabindex="-1">Cookie的Secure和HttpOnly 标记 <a class="header-anchor" href="#cookie的secure和httponly-标记" aria-label="Permalink to &quot;Cookie的Secure和HttpOnly 标记&quot;">​</a></h3><p>标记为 <code>Secure</code> 的 <code>Cookie</code> 只应通过被 <code>HTTPS</code> 协议加密过的请求发送给服务端。</p><p>标记为 <code>Secure</code> 的 <code>Cookie</code> 只应通过被 <code>HTTPS</code> 协议加密过的请求发送给服务端。但即便设置了 <code>Secure</code> 标记，敏感信息也不应该通过 <code>Cookie</code> 传输，因为 <code>Cookie</code> 有其固有的不安全性，<code>Secure</code> 标记也无法提供确实的安全保障</p><p>通过 <code>JavaScript</code> 的 <code>Document.cookie</code> <code>API</code> 是无法访问带有 <code>HttpOnly</code> 标记的 <code>cookie</code>。这么做是为了避免跨域脚本攻击（<code>XSS</code>）</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly</span></span></code></pre></div><h3 id="cookie的作用域" tabindex="-1">Cookie的作用域 <a class="header-anchor" href="#cookie的作用域" aria-label="Permalink to &quot;Cookie的作用域&quot;">​</a></h3><p><code>Domain</code> 和 <code>Path</code> 标识定义了 <code>Cookie</code> 的作用域：即 <code>Cookie</code> 应该发送给哪些 <code>URL</code>。</p><p><code>Domain</code> 标识指定了哪些主机可以接受 <code>Cookie</code>。如果不指定，默认为当前的主机（不包含子域名）。如果指定了 <code>Domain</code>，则一般包含子域名。</p><p>例如，如果设置 <code>Domain=mozilla.org</code>，则 <code>Cookie</code> 也包含在子域名中（如<code>developer.mozilla.org</code>）。</p><p><code>Path</code> 标识指定了主机下的哪些路径可以接受 <code>Cookie</code>（该 <code>URL</code> 路径必须存在于请求 <code>URL</code> 中）。以字符 %x2F (&quot;/&quot;) 作为路径分隔符，子路径也会被匹配。</p><p>例如，设置 <code>Path=/docs</code>，则以下地址都会匹配：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">/docs</span></span>
<span class="line"><span style="color:#A6ACCD;">/docs/Web/</span></span>
<span class="line"><span style="color:#A6ACCD;">/docs/Web/HTTP</span></span></code></pre></div><h3 id="samesite-cookies" tabindex="-1">SameSite Cookies <a class="header-anchor" href="#samesite-cookies" aria-label="Permalink to &quot;SameSite Cookies&quot;">​</a></h3><p><code>SameSite Cookie</code> 允许服务器要求某个 <code>cookie</code> 在跨站请求时不会被发送，从而可以阻止跨站请求伪造攻击</p><ul><li><code>None</code> 浏览器会在同站请求、跨站请求下继续发送 <code>cookies</code>，不区分大小写。【旧版本 <code>chrome</code> 默认 <code>Chrome 80</code> 版本之前】</li><li><code>Strict</code> 浏览器将只在访问相同站点时发送 <code>cookie</code>。</li><li><code>Lax</code> 将会为一些跨站子请求保留，如图片加载或者 <code>frames</code> 的调用，但只有当用户从外部站点导航到 <code>URL</code> 时才会发送。如 <code>link</code> 链接</li></ul><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">Set-Cookie: key=value; SameSite=Strict</span></span>
<span class="line"><span style="color:#A6ACCD;">None Strict Lax</span></span></code></pre></div><p>在新版本的浏览器（<code>Chrome 80</code> 之后）中，<code>SameSite</code> 的默认属性是 <code>SameSite=Lax</code>。换句话说，当 <code>Cookie</code> 没有设置 <code>SameSite</code> 属性时，将会视作 <code>SameSite</code> 属性被设置为 <code>Lax</code> —— 这意味着 <code>Cookies</code> 将不会在当前用户使用时被自动发送。如果想要指定 <code>Cookies</code> 在同站、跨站请求都被发送，那么需要明确指定<code>SameSite</code> 为 <code>None</code>。因为这一点，我们需要好好排查旧系统是否明确指定 <code>SameSite</code>，以及推荐新系统明确指定 <code>SameSite</code>，以兼容新旧版本 <code>Chrome</code></p><p>更多 <code>cookie</code> 相关，可以查看我之前总结的一篇关于 <code>cookie</code> 的文章 <strong>前端须知的 Cookie 知识小结</strong>[7]</p><h2 id="http访问控制-cors" tabindex="-1">HTTP访问控制（CORS） <a class="header-anchor" href="#http访问控制-cors" aria-label="Permalink to &quot;HTTP访问控制（CORS）&quot;">​</a></h2><p>跨域资源共享（<code>CORS</code>）是一种机制，它使用额外的 <code>HTTP</code> 头告诉浏览器，让运行在一个 <code>origin</code> (<code>domain</code>) 上的 <code>web</code> 应用被准许访问来自不同源服务器上的指定的资源</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvNDFoJrQ5cVQM7F4SKEztgUIFoibfxk6CIqBa1gzuEDNcvsSwQSqanGSw/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>跨域资源共享标准新增了一组 <code>HTTP</code> 首部字段，允许服务器声明哪些源站通过浏览器有权限访问哪些资源。</p><h3 id="简单请求" tabindex="-1">简单请求 <a class="header-anchor" href="#简单请求" aria-label="Permalink to &quot;简单请求&quot;">​</a></h3><p>简单请求（不会触发 <code>CORS</code> 的预检请求）需要同时满足以下三点：</p><ul><li>方法是 <code>GET/HEAD/POST</code> 之一</li><li><code>Content-Type</code> 的值仅限 <code>text/plain</code>、<code>multipart/form-data</code>、<code>application/x-www-form-urlencoded</code> 三者之一</li><li><code>HTTP</code> 头部不能超过以下字段：<code>Accept</code>、<code>Accept-Language</code>、<code>Content-Language``Content-Type</code>（需要注意额外的限制）<code>DPR</code>、<code>Downlink</code>、<code>Save-Data</code>、<code>Viewport-Width</code>、<code>Width</code></li></ul><p>以下为一个简单请求的请求报文以及响应报文</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvNxicTnyzNjev1XibjnRXJYd3ZO8ULKzBu0GPtVLBjeE1x0ccKw9WoJ7xA/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>简化以下：</p><img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvNT4qibNDPb1c87QtWFIJf4mQWibnM7rtoBAzgDR5jOZicOO5zicPNbpUSuw/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片" style="zoom:80%;"><p>请求首部字段 <code>Origin</code> 表明该请求来源于 <code>http://foo.example</code></p><p>本例中，服务端返回的 <code>Access-Control-Allow-Origin: *</code> 表明，该资源可以被任意外域访问。如果服务端仅允许来自 <code>http://foo.example</code> 的访问，该首部字段的内容如下：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">Access-Control-Allow-Origin: http://foo.example</span></span></code></pre></div><p><code>Access-Control-Allow-Origin</code> 应当为 * 或者包含由 <code>Origin</code> 首部字段所指明的域名。</p><h3 id="预检请求" tabindex="-1">预检请求 <a class="header-anchor" href="#预检请求" aria-label="Permalink to &quot;预检请求&quot;">​</a></h3><p>规范要求，对那些可能对服务器数据产生副作用的 <code>HTTP</code> 请求方法。浏览器必须首先使用 <code>OPTIONS</code> 方法发起一个预检请求（<code>preflight request</code>），从而获知服务端是否允许该跨域请求。</p><p>服务器确认允许之后，才发起实际的 <code>HTTP</code> 请求。在预检请求的返回中，服务器端也可以通知客户端，是否需要携带身份凭证（包括 <code>Cookies</code> 和 <code>HTTP</code> 认证相关数据）</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/betIP9fVPicP9mOWh8f5hp8VpYXOEAAvNyW8Ug3CAjia0LfZQIBkhH2k9tNNEqCVPswGtTHoSiaboOcnf5ib22YTpg/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>预检请求中同时携带了下面两个首部字段：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">Access-Control-Request-Method: POST</span></span>
<span class="line"><span style="color:#A6ACCD;">Access-Control-Request-Headers: X-PINGOTHER, Content-Type</span></span></code></pre></div><p>首部字段 <code>Access-Control-Request-Method</code> 告知服务器，实际请求将使用 <code>POST</code> 方法。首部字段 <code>Access-Control-Request-Headers</code> 告知服务器，实际请求将携带两个自定义请求首部字段：<code>X-PINGOTHER</code> 与 <code>Content-Type</code>。服务器据此决定，该实际请求是否被允许。</p><p>预检请求的响应中，包括了以下几个字段</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">Access-Control-Allow-Origin: http://foo.example</span></span>
<span class="line"><span style="color:#A6ACCD;">// 表明服务器允许客户端使用 POST, GET 和 OPTIONS 方法发起请求</span></span>
<span class="line"><span style="color:#A6ACCD;">Access-Control-Allow-Methods: POST, GET, OPTIONS</span></span>
<span class="line"><span style="color:#A6ACCD;">// 表明服务器允许请求中携带字段 X-PINGOTHER 与 Content-Type</span></span>
<span class="line"><span style="color:#A6ACCD;">Access-Control-Allow-Headers: X-PINGOTHER, Content-Type</span></span>
<span class="line"><span style="color:#A6ACCD;">// 表明该响应的有效时间为 86400 秒，也就是 24 小时。在有效时间内，浏览器无须为同一请求再次发起预检请求。</span></span>
<span class="line"><span style="color:#A6ACCD;">Access-Control-Max-Age: 86400</span></span></code></pre></div><p>HTTP 请求和响应 一般而言，对于跨域 <code>XMLHttpRequest</code> 或 <code>Fetch</code> 请求，浏览器不会发送身份凭证信息。如果要发送凭证信息，需要设置 <code>XMLHttpRequest</code> 的某个特殊标志位。比如说 <code>XMLHttpRequest</code> 的 <code>withCredentials</code> 标志设置为 <code>true</code>，则可以发送 <code>cookie</code> 到服务端。</p><p>对于附带身份凭证的请求，服务器不得设置 <code>Access-Control-Allow-Origin</code> 的值为“<em>”。这是因为请求的首部中携带了 <code>Cookie</code> 信息，如果 <code>Access-Control-Allow-Origin</code> 的值为“</em>”，请求将会失败。而将 <code>Access-Control-Allow-Origin</code> 的值设置为 <code>http://foo.example</code>，则请求将成功执行。</p><p><code>CORS</code> 涉及到的请求和响应头如下：<code>HTTP</code> 响应首部字段</p><ul><li><code>Access-Control-Allow-Origin</code> 允许访问该资源的外域 <code>URI</code>。对于不需要携带身份凭证的请求，服务器可以指定该字段的值为通配符，表示允许来自所有域的请求。</li><li><code>Access-Control-Expose-Headers</code> 头让服务器把允许浏览器访问的头放入白名单</li><li><code>Access-Control-Max-Age</code> 头指定了 <code>preflight</code> 请求的结果能够被缓存多久</li><li><code>Access-Control-Allow-Credentials</code> 头指定了当浏览器的 <code>credentials</code> 设置为 <code>true</code> 时是否允许浏览器读取 <code>response</code> 的内容。</li><li><code>Access-Control-Allow-Methods</code> 首部字段用于预检请求的响应。其指明了实际请求所允许使用的 <code>HTTP</code> 方法。</li><li><code>Access-Control-Allow-Headers</code> 首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段。</li></ul><p><code>HTTP</code> 请求首部字段</p><ul><li><code>Origin</code> 首部字段表明预检请求或实际请求的源站</li><li><code>Access-Control-Request-Method</code> 首部字段用于预检请求。其作用将实际请求所使用的 HTTP 方法告诉服务器</li><li><code>Access-Control-Request-Headers</code> 首部字段用于预检请求。其作用，将实际请求所携带的首部字段告诉服器</li></ul><h1 id="前端缓存⭐" tabindex="-1">前端缓存⭐ <a class="header-anchor" href="#前端缓存⭐" aria-label="Permalink to &quot;前端缓存⭐&quot;">​</a></h1><h2 id="什么是web缓存" tabindex="-1">什么是web缓存？ <a class="header-anchor" href="#什么是web缓存" aria-label="Permalink to &quot;什么是web缓存？&quot;">​</a></h2><h3 id="web缓存分类" tabindex="-1">web缓存分类 <a class="header-anchor" href="#web缓存分类" aria-label="Permalink to &quot;web缓存分类&quot;">​</a></h3><p>web缓存主要指的是两部分：浏览器缓存和http缓存。其中http缓存是web缓存的核心，是最重要的那一部分</p><blockquote><p>浏览器缓存：比如,localStorage,sessionStorage,cookie等等。这些功能主要用于缓存一些必要的数据，比如用户信息。比如需要携带到后端的参数。亦或者是一些列表数据等等。</p></blockquote><blockquote><p>不过这里需要注意。像localStorage，sessionStorage这种用户缓存数据的功能，他只能保存5M左右的数据，多了不行。cookie则更少，大概只能有4kb的数据。这篇文章重点讲解的是：前端http缓存</p></blockquote><h3 id="http缓存" tabindex="-1">http缓存 <a class="header-anchor" href="#http缓存" aria-label="Permalink to &quot;http缓存&quot;">​</a></h3><blockquote><p>官方介绍:Web 缓存是可以自动保存常见文档副本的 HTTP 设备。当 Web 请求抵达缓存时， 如果本地有“已缓存的”副本，就可以从本地存储设备而不是原始服务器中提取这 个文档。</p></blockquote><p>举个例子</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.12.30/202210251100128.png" alt="image-20221025110025062" style="zoom:80%;"><blockquote><p>看图，问题就是出在，服务器需要处理http的请求，并且http去传输数据，需要带宽，带宽是要钱买的啊。而我们缓存，就是为了让服务器不去处理这个请求，客户端也可以拿到数据。</p></blockquote><blockquote><p>注意，我们的缓存主要是针对html,css,img等静态资源，常规情况下，我们不会去缓存一些动态资源，因为缓存动态资源的话，数据的实时性就不会不太好，所以我们一般都只会去缓存一些不太容易被改变的静态资源。</p></blockquote><h2 id="前端缓存优缺点" tabindex="-1">前端缓存优缺点 <a class="header-anchor" href="#前端缓存优缺点" aria-label="Permalink to &quot;前端缓存优缺点&quot;">​</a></h2><p>先说说，缓存可以解决什么问题。</p><ul><li><strong>减少不必要的网络传输，节约宽带（就是省钱）</strong></li><li><strong>更快的加载页面（就是加速）</strong></li><li><strong>减少服务器负载，避免服务器过载的情况出现。（就是减载）</strong></li></ul><p>再说说缺点</p><ul><li>占内存（有些缓存会被存到内存中）</li></ul><blockquote><p>其实日常的开发中，我们最最最最关心的，还是&quot;更快的加载页面&quot;;尤其是对于react/vue等SPA（单页面）应用来说，首屏加载是老生常谈的问题。这个时候，缓存就显得非常重要。不需要往后端请求，直接在缓存中读取。速度上，会有显著的提升。是一种提升网站性能与用户体验的有效策略。</p></blockquote><h2 id="http缓存分类" tabindex="-1">http缓存分类 <a class="header-anchor" href="#http缓存分类" aria-label="Permalink to &quot;http缓存分类&quot;">​</a></h2><p>http缓存又分为两种两种缓存，<strong>强制缓存</strong>和<strong>协商缓存</strong>,我们来深度剖析一下<strong>强制缓存和协商缓存各自的优劣以及他们的使用场景以及使用原理</strong></p><p><strong>http缓存流程图↓</strong></p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.12.30/202210251104873.png" alt="image-20221025110424798" style="zoom:80%;"><h2 id="强制缓存" tabindex="-1">强制缓存 <a class="header-anchor" href="#强制缓存" aria-label="Permalink to &quot;强制缓存&quot;">​</a></h2><blockquote><p>强制缓存，我们简称强缓存。从强制缓存的角度触发，如果浏览器判断请求的目标资源有效命中强缓存，如果命中，则可以直接从内存中读取目标资源，无需与服务器做任何通讯。</p></blockquote><h3 id="基于expires字段实现强缓存-废弃" tabindex="-1">基于Expires字段实现强缓存(废弃) <a class="header-anchor" href="#基于expires字段实现强缓存-废弃" aria-label="Permalink to &quot;基于Expires字段实现强缓存(废弃)&quot;">​</a></h3><p>在以前，我们通常会使用响应头的<code>Expires</code>字段去实现强缓存。</p><p><code>Expires</code>字段的作用是，设定一个强缓存时间。在此时间范围内，则从内存（或磁盘）中读取缓存返回。</p><p>比如说将某一资源设置响应头为:Expires:new Date(&quot;2022-7-30 23:59:59&quot;)；</p><p>那么，该资源在2022-7-30 23:59:59 之前，都会去本地的磁盘（或内存）中读取，不会去服务器请求。</p><p>但是，<strong><code>Expires</code>已经被废弃了</strong>。对于强缓存来说，<code>Expires</code>已经不是实现强缓存的首选。</p><blockquote><p>因为Expires判断强缓存是否过期的机制是:获取本地时间戳，并对先前拿到的资源文件中的<code>Expires</code>字段的时间做比较。来判断是否需要对服务器发起请求。这里有一个巨大的漏洞：“如果我本地时间不准咋办？”</p></blockquote><blockquote><p>是的，<code>Expires</code>过度依赖本地时间，如果本地与服务器时间不同步，就会出现资源无法被缓存或者资源永远被缓存的情况。所以，<code>Expires</code>字段几乎不被使用了。现在的项目中，我们并不推荐使用<code>Expires</code>，强缓存功能通常使用<code>cache-control</code>字段来代替<code>Expires</code>字段。</p></blockquote><p>没想到吧，整半天，这个属性是废的。</p><h3 id="基于cache-control实现强缓存⭐" tabindex="-1">基于Cache-control实现强缓存⭐ <a class="header-anchor" href="#基于cache-control实现强缓存⭐" aria-label="Permalink to &quot;基于Cache-control实现强缓存⭐&quot;">​</a></h3><p><code>Cache-control</code>这个字段在http1.1中被增加，<code>Cache-control</code>完美解决了<code>Expires</code>本地时间和服务器时间不同步的问题。是当下的项目中实现强缓存的最常规方法。</p><h4 id="cache-control使用分析" tabindex="-1">Cache-control使用分析 <a class="header-anchor" href="#cache-control使用分析" aria-label="Permalink to &quot;Cache-control使用分析&quot;">​</a></h4><p><code>Cache-control</code>的使用方法页很简单，只要在资源的响应头上写上需要缓存多久就好了，单位是秒。比如↓</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#676E95;font-style:italic;">//往响应头中写入需要缓存的时间</span></span>
<span class="line"><span style="color:#A6ACCD;">res</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">writeHead</span><span style="color:#A6ACCD;">(</span><span style="color:#F78C6C;">200</span><span style="color:#89DDFF;">,{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">&#39;</span><span style="color:#F07178;">Cache-Control</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">max-age=10</span><span style="color:#89DDFF;">&#39;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span></code></pre></div><p>下图的意思就是，从该资源第一次返回的时候开始，往后的10秒钟内如果该资源被再次请求，则从缓存中读取。</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.12.30/202210251116513.png" alt="image-20221025111625463" style="zoom:80%;"><p><strong>Cache-Control:max-age=N，N就是需要缓存的秒数。从第一次请求资源的时候开始，往后N秒内，资源若再次请求，则直接从磁盘（或内存中读取），不与服务器做任何交互。</strong></p><p><code>Cache-control</code>中因为max-age后面的值是一个滑动时间，从服务器第一次返回该资源时开始倒计时。所以也就不需要比对客户端和服务端的时间，解决了<code>Expires</code>所存在的巨大漏洞。</p><h4 id="cache-control属性" tabindex="-1">Cache-control属性 <a class="header-anchor" href="#cache-control属性" aria-label="Permalink to &quot;Cache-control属性&quot;">​</a></h4><p><code>Cache-control</code>有<strong>max-age</strong>、<strong>s-maxage</strong>、<strong>no-cache</strong>、<strong>no-store</strong>、<strong>private</strong>、<strong>public</strong>这六个属性。</p><ul><li><strong>max-age</strong>决定客户端资源被缓存多久。</li><li><strong>s-maxage</strong>决定代理服务器缓存的时长。</li><li><strong>no-cache</strong>表示是强制进行协商缓存。</li><li><strong>no-store</strong>是表示禁止任何缓存策略。</li><li><strong>public</strong>表示资源即可以被浏览器缓存也可以被代理服务器缓存。</li><li><strong>private</strong>表示资源只能被浏览器缓存。</li></ul><h4 id="no-cache和no-store" tabindex="-1">no-cache和no-store <a class="header-anchor" href="#no-cache和no-store" aria-label="Permalink to &quot;no-cache和no-store&quot;">​</a></h4><p><strong>no_cache</strong>是<code>Cache-control</code>的一个属性。它并不像字面意思一样禁止缓存，实际上，<strong>no-cache</strong>的意思是强制进行协商缓存。如果某一资源的<code>Cache-control</code>中设置了<strong>no-cache</strong>，那么该资源会直接跳过强缓存的校验，直接去服务器进行协商缓存。而<strong>no-store</strong>就是禁止所有的缓存策略了。</p><blockquote><p>注意，no-cache和no-store是一组互斥属性，这两个属性不能同时出现在<code>Cache-Control</code>中。</p></blockquote><h4 id="public和private" tabindex="-1">public和private <a class="header-anchor" href="#public和private" aria-label="Permalink to &quot;public和private&quot;">​</a></h4><p>一般请求是从客户端直接发送到服务端，如下↓</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.12.30/202210251117020.png" alt="image-20221025111749967" style="zoom:80%;"><p>但有些情况下是例外的：比如，出现代理服务器，如下↓</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.12.30/202210251117466.png" alt="image-20221025111759422" style="zoom:80%;"><p>而<strong>public</strong>和<strong>private</strong>就是决定资源是否可以在代理服务器进行缓存的属性。</p><p>其中，<strong>public</strong>表示资源在客户端和代理服务器都可以被缓存。</p><p><strong>private</strong>则表示资源只能在客户端被缓存，拒绝资源在代理服务器缓存。</p><p>如果这两个属性值都没有被设置，则默认为<strong>private</strong></p><blockquote><p>注意，<strong>public</strong>和<strong>private</strong>也是一组互斥属性。他们两个不能同时出现在响应头的<code>cache-control</code>字段中。</p></blockquote><h4 id="max-age和s-maxage" tabindex="-1">max-age和s-maxage <a class="header-anchor" href="#max-age和s-maxage" aria-label="Permalink to &quot;max-age和s-maxage&quot;">​</a></h4><p><strong>max-age</strong>表示的时间资源在客户端缓存的时长，而<strong>s-maxage</strong>表示的是资源在代理服务器可以缓存的时长。</p><p>在一般的项目架构中<strong>max-age</strong>就够用。</p><p>而<strong>s-maxage</strong>因为是代理服务端的缓存时长，他必须和上面说的<strong>public</strong>属性一起使用（public属性表示资源可以在代理服务器中缓存）。</p><blockquote><p>注意，<strong>max-age</strong>和<strong>s-maxage</strong>并不互斥。他们可以一起使用。</p></blockquote><p>那么,Cache-control如何设置多个值呢？用逗号分割，如下↓</p><div class="language-c"><button title="Copy Code" class="copy"></button><span class="lang">c</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">Cache</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">control:max</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">age</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">10000</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">s</span><span style="color:#89DDFF;">-</span><span style="color:#A6ACCD;">maxage</span><span style="color:#89DDFF;">=</span><span style="color:#F78C6C;">200000</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;">public</span></span></code></pre></div><p><strong>强制缓存就是以上这两种方法了。现在我们回过头来聊聊，<code>Expires</code>难道就一点用都没有了吗？也不是，虽然<code>Cache-control是Expires</code>的完全替代品，但是如果要考虑向下兼容的话，在<code>Cache-control</code>不支持的时候，还是要使用<code>Expires</code>，这也是我们当前使用的这个属性的唯一理由。</strong></p><h2 id="协商缓存-1" tabindex="-1">协商缓存 <a class="header-anchor" href="#协商缓存-1" aria-label="Permalink to &quot;协商缓存&quot;">​</a></h2><blockquote><p>温馨提示:协商缓存的内容会有一点点绕。需要仔细阅读。</p></blockquote><h3 id="基于last-modified的协商缓存" tabindex="-1">基于last-modified的协商缓存 <a class="header-anchor" href="#基于last-modified的协商缓存" aria-label="Permalink to &quot;基于last-modified的协商缓存&quot;">​</a></h3><blockquote><ol><li>首先需要在服务器端读出文件修改时间，</li><li>将读出来的修改时间赋给响应头的<code>last-modified</code>字段。</li><li>最后设置<code>Cache-control:no-cache</code></li></ol></blockquote><p>三步缺一不可。如下图↓</p><img src="https://mmbiz.qpic.cn/mmbiz/bwG40XYiaOKlBpSDlohKWtVfY1icHaYTNYibZsxQFMqcJTwJOyVWalm33JyW3oeiaml7CoSLzOwh6QgD7ujt76eM1w/640?wx_fmt=jpeg&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片" style="zoom:80%;"><p>注意圈出来的三行。</p><p>第一行，读出修改时间。</p><p>第二行，给该资源响应头的<code>last-modified</code>字段赋值修改时间</p><p>第三行，给该资源响应头的<code>Cache-Control</code>字段值设置为:no-cache.(上文有介绍，Cache-control:no-cache的意思是跳过强缓存校验，直接进行协商缓存。)</p><p><strong>还没完。到这里还无法实现协商缓存</strong></p><p>当客户端读取到<code>last-modified</code>的时候，会在下次的请求标头中携带一个字段:<code>If-Modified-Since</code>。</p><p><img src="https://mmbiz.qpic.cn/mmbiz/bwG40XYiaOKlBpSDlohKWtVfY1icHaYTNYt8oGNKRC3jGicar0AaH8nvPBGbGGficPbtJibDag80uWpthYBf4t2CTmg/640?wx_fmt=jpeg&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片">image.png</p><p>而这个请求头中的<code>If-Modified-Since</code>就是服务器第一次修改时候给他的时间，也就是上图中的</p><p><img src="https://mmbiz.qpic.cn/mmbiz/bwG40XYiaOKlBpSDlohKWtVfY1icHaYTNYoMuaQT1Eq8acKrgXDcLmuGpB5bQaJ1q6mxpgZ3iclVibia7MbgqLVnqJg/640?wx_fmt=jpeg&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片">这一行。</p><p><strong>那么之后每次对该资源的请求，都会带上<code>If-Modified-Since</code>这个字段，而务端就需要拿到这个时间并再次读取该资源的修改时间，让他们两个做一个比对来决定是读取缓存还是返回新的资源。</strong></p><p>如图↓</p><img src="https://mmbiz.qpic.cn/mmbiz/bwG40XYiaOKlBpSDlohKWtVfY1icHaYTNYEialwJnHGHh9fibdz9nAHOWkjxhaicaLZbPQlpBLfFcjXjK9h93jYbmAw/640?wx_fmt=jpeg&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片" style="zoom:80%;"><p>这样，就是协商缓存的所有操作了。看到这里，有些小伙伴可能有些迷糊了。</p><p>没关系，我们用一张图来解释下协商缓存。</p><img src="https://mmbiz.qpic.cn/mmbiz/bwG40XYiaOKlBpSDlohKWtVfY1icHaYTNYu6ibh9NBlBcLDusVnCJey7dhRFfjTblgUpZFJoxYOg9puiaTCrWurmqg/640?wx_fmt=jpeg&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片" style="zoom:80%;"><p><strong>使用以上方式的协商缓存已经存在两个非常明显的漏洞。这两个漏洞都是基于文件是通过比较修改时间来判断是否更改而产生的。</strong></p><p><strong>1.因为是更具文件修改时间来判断的，所以，在文件内容本身不修改的情况下，依然有可能更新文件修改时间（比如修改文件名再改回来），这样，就有可能文件内容明明没有修改，但是缓存依然失效了。</strong></p><p><strong>2.当文件在极短时间内完成修改的时候（比如几百毫秒）。因为文件修改时间记录的最小单位是秒，所以，如果文件在几百毫秒内完成修改的话，文件修改时间不会改变，这样，即使文件内容修改了，依然不会 返回新的文件。</strong></p><p><strong>为了解决上述的这两个问题。从<code>http1.1</code>开始新增了一个头信息，<code>ETag</code>(Entity 实体标签)</strong></p><h3 id="基础etag的协商缓存" tabindex="-1">基础ETag的协商缓存 <a class="header-anchor" href="#基础etag的协商缓存" aria-label="Permalink to &quot;基础ETag的协商缓存&quot;">​</a></h3><p>不用太担心，如果你已经理解了上面比较时间戳形式的协商缓存的话，<code>ETag</code>对你来说不会有难度。</p><p><code>ETag</code>就是将原先协商缓存的比较<strong>时间戳</strong>的形式修改成了比较<strong>文件指纹</strong>。</p><blockquote><p>文件指纹:根据文件内容计算出的唯一哈希值。文件内容一旦改变则指纹改变。</p></blockquote><p>我们来看一下流程↓</p><p>1.第一次请求某资源的时候，服务端读取文件并计算出文件指纹，将文件指纹放在响应头的<code>etag</code>字段中跟资源一起返回给客户端。</p><p>2.第二次请求某资源的时候，客户端自动从缓存中读取出上一次服务端返回的<code>ETag</code>也就是文件指纹。并赋给请求头的<code>if-None-Match</code>字段，让上一次的文件指纹跟随请求一起回到服务端。</p><p>3.服务端拿到请求头中的<code>is-None-Match</code>字段值（也就是上一次的文件指纹），并再次读取目标资源并生成文件指纹，两个指纹做对比。如果两个文件指纹完全吻合，说明文件没有被改变，则直接返回304状态码和一个空的响应体并return。如果两个文件指纹不吻合，则说明文件被更改，那么将新的文件指纹重新存储到响应头的<code>ETag</code>中并返回给客户端</p><p>代码图例↓</p><p><img src="https://mmbiz.qpic.cn/mmbiz/bwG40XYiaOKlBpSDlohKWtVfY1icHaYTNYjwDA1yYnibk4Q92GtwWfVXpzZiaIicGpHMNo6HQl1kPZKfnTfJibBs0yWQ/640?wx_fmt=jpeg&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片">image.png</p><p>流程示例图↓</p><p><img src="https://mmbiz.qpic.cn/mmbiz/bwG40XYiaOKlBpSDlohKWtVfY1icHaYTNY0OOOpia3xjCYuzC3yoOE6ACUibLt2lMLKicgq4YYocdicZ3obnsibT3GaXg/640?wx_fmt=jpeg&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片">image.png</p><blockquote><p>从校验流程上来说，协商缓存的修改时间比对和文件指纹比对，几乎是一样的。</p></blockquote><h3 id="etag也有缺点" tabindex="-1">ETag也有缺点 <a class="header-anchor" href="#etag也有缺点" aria-label="Permalink to &quot;ETag也有缺点&quot;">​</a></h3><ul><li><strong>ETag需要计算文件指纹这样意味着，服务端需要更多的计算开销。。如果文件尺寸大，数量多，并且计算频繁，那么ETag的计算就会影响服务器的性能。显然，ETag在这样的场景下就不是很适合。</strong></li><li><strong>ETag有强验证和弱验证，所谓将强验证，ETag生成的哈希码深入到每个字节。哪怕文件中只有一个字节改变了，也会生成不同的哈希值，它可以保证文件内容绝对的不变。但是，强验证非常消耗计算量。ETag还有一个弱验证，弱验证是提取文件的部分属性来生成哈希值。因为不必精确到每个字节，所以他的整体速度会比强验证快，但是准确率不高。会降低协商缓存的有效性。</strong></li></ul><blockquote><p>值得注意的一点是，不同于<code>cache-control</code>是<code>expires</code>的完全替代方案(说人话:能用<code>cache-control</code>就不要用<code>expiress</code>)。<code>ETag</code>并不是<code>last-modified</code>的完全替代方案。而是<code>last-modified</code>的补充方案（说人话：项目中到底是用<code>ETag</code>还是<code>last-modified</code>完全取决于业务场景，这两个没有谁更好谁更坏）。</p></blockquote><h2 id="如何设置缓存" tabindex="-1">如何设置缓存 <a class="header-anchor" href="#如何设置缓存" aria-label="Permalink to &quot;如何设置缓存&quot;">​</a></h2><h3 id="前端角度" tabindex="-1">前端角度 <a class="header-anchor" href="#前端角度" aria-label="Permalink to &quot;前端角度&quot;">​</a></h3><blockquote><p>你什么都不用干，缓存是缓存在前端，但实际上代码是后端的同学来写的。如果你需要实现前端缓存的话啊，通知后端的同学加响应头就好了。</p></blockquote><h3 id="后端角度" tabindex="-1">后端角度 <a class="header-anchor" href="#后端角度" aria-label="Permalink to &quot;后端角度&quot;">​</a></h3><blockquote><p>请参考文章，虽然文章里的后端是使用node.js写的，但我写了详细的注释。对于后端的同学来说。应该不难看懂。</p></blockquote><h2 id="哪些文件对应哪些缓存⭐⭐" tabindex="-1">哪些文件对应哪些缓存⭐⭐ <a class="header-anchor" href="#哪些文件对应哪些缓存⭐⭐" aria-label="Permalink to &quot;哪些文件对应哪些缓存⭐⭐&quot;">​</a></h2><p>有哈希值的文件设置强缓存即可。没有哈希值的文件（比如index.html）设置协商缓存</p><h3 id="有哈希值的文件设置强缓存" tabindex="-1">有哈希值的文件设置强缓存 <a class="header-anchor" href="#有哈希值的文件设置强缓存" aria-label="Permalink to &quot;有哈希值的文件设置强缓存&quot;">​</a></h3><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.12.30/202210251127225.png" alt="image-20221025112714179" style="zoom:80%;"><p>这是我打完包之后的css文件。大家是否注意到。我划了红线的部分。明显，这绝不是我的文件名。这串和乱码一样的字符串叫<code>哈希值</code>。每次打包之后都会生产一串新的<code>哈希值</code>并追加到我们的文件名中。哈希值是打包后的文件名的一部分。</p><p>我们给css设置强缓存，哪怕缓存1W年。只要我们重新打包，生产新的哈希值。那么文件名就更改了。对于机器来说，更改了文件名的文件，就是一个新的文件。</p><p><em>举个例子👇</em></p><p>比如，有一个css文件a1</p><p>第一次打包a1.css文件追加哈希值变成了 a1.aaaaa.css,我们给a1.aaaaa.css设置了强缓存1W年。</p><p>然后项目改动，我们又打包了一次。打包后生产新的哈希值，a1.aaaaa.css变成了a1.bbbbb.css文件。那么当我们第一次访问a1.bbbbb.css文件的时候是不会被缓存。因为1W年的缓存是给a1.aaaaa.css文件做的。关我a1.bbbbb.css文件什么事？这样我们也就能拿到最新的改动。</p><p>其他可以被webpack生成哈希值的文件同理。</p><h3 id="index-html使用协商缓存" tabindex="-1">index.html使用协商缓存 <a class="header-anchor" href="#index-html使用协商缓存" aria-label="Permalink to &quot;index.html使用协商缓存&quot;">​</a></h3><p>既然img/css这些文件都可以用强缓存。通过更改文件名的方式来获取最新的数据，为什么我堂堂index.html就要用协商呢？我给大家看个图</p><p><img src="https://mmbiz.qpic.cn/mmbiz/bwG40XYiaOKlBpSDlohKWtVfY1icHaYTNYwqMlLxuItSia26iaVTibt0aszIwkWz8Joic8MQF9mO5ajV0TwgX9K9ibHqg/640?wx_fmt=jpeg&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>因为一般情况下，index.html是不会设置哈希值的。（具体得看自己项目下的dist文件夹）</p><blockquote><p>注意：哈希值是需要webpack生成的。不是天生的。不过有些框架会自带（比如我使用的umi.js）,设置缓存前务必看下自己的dist文件。因为如果没有配置的话，你可能所有文件都不带哈希值。</p></blockquote><h2 id="总结一下" tabindex="-1">总结一下 <a class="header-anchor" href="#总结一下" aria-label="Permalink to &quot;总结一下&quot;">​</a></h2><ul><li>http缓存可以减少宽带流量，加快响应速度。</li><li>关于强缓存，<code>cache-control</code>是<code>Expires</code>的完全替代方案，在可以使用<code>cache-control</code>不要使用<code>expires</code></li><li>关于协商缓存,<code>etag</code>并不是<code>last-modified</code>的完全替代方案，而是补充方案，具体用哪一个，取决于业务场景。</li><li>有些缓存是从磁盘读取，有些缓存是从内存读取，有什么区别？答：从内存读取的缓存更快。</li><li>所有带304的资源都是协商缓存，所有标注（从内存中读取/从磁盘中读取）的资源都是强缓存。</li></ul><h1 id="页面关闭时监控前端上传数据" tabindex="-1">页面关闭时监控前端上传数据 <a class="header-anchor" href="#页面关闭时监控前端上传数据" aria-label="Permalink to &quot;页面关闭时监控前端上传数据&quot;">​</a></h1><p>本文以 <strong>“前端监控上报数据”</strong> 的业务场景，重点解析在 <strong>页面实例关闭</strong> 时，如何将监控数据上传到服务端的解决方案。 其中，涉及到4种方案，分别为：</p><ul><li>同步XMLHttpRequest</li><li>img.src</li><li>navigator.sendBeacon</li><li>fetch keepalive</li></ul><h2 id="同步xmlhttprequest" tabindex="-1">同步XMLHttpRequest <a class="header-anchor" href="#同步xmlhttprequest" aria-label="Permalink to &quot;同步XMLHttpRequest&quot;">​</a></h2><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> data </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> JSON</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">stringify</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">     </span><span style="color:#F07178;">time</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> performance</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">now</span><span style="color:#A6ACCD;">()</span></span>
<span class="line"><span style="color:#A6ACCD;">   </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">var</span><span style="color:#A6ACCD;"> xhr </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">new</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">XMLHttpRequest</span><span style="color:#A6ACCD;">()</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;font-style:italic;">// 第三个参数false，表示当前请求是同步</span></span>
<span class="line"><span style="color:#A6ACCD;">xhr</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">open</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">post</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">http://api.wangxiaokai.vip/test</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">false</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">xhr</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">setRequestHeader</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">content-type</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">application/json</span><span style="color:#89DDFF;">&#39;</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">xhr</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">onreadystatechange</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;"> </span><span style="color:#676E95;font-style:italic;">// 发送成功后，页面已销毁，所以这里执行不了</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">xhr</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">send</span><span style="color:#A6ACCD;">(data)</span><span style="color:#89DDFF;">;</span></span></code></pre></div><p><strong>为什么同步XMLHttpRequest可以在页面关闭时上传数据？</strong></p><p><strong>同步请求阻止代码的执行</strong>，这会导致屏幕上出现“冻结”和无响应的用户体验。</p><p>然而，在新版的chrome（版本号大于80）已经不支持。以下是官方的公告片段：</p><blockquote><p>Chrome now disallows synchronous calls to <code>XMLHTTPRequest()</code> during page dismissal when the page is being navigated away from or is closed by the user. This applies to <code>beforeunload</code>, <code>unload</code>, <code>pagehide</code>, and <code>visibilitychange</code>.</p></blockquote><p>详细解释可阅读 <strong>Disallow Synchronous XMLHTTPRequest() in Page Dismissal</strong>[2]</p><p><strong>缺点</strong></p><ul><li>用户体验差，会阻塞页面切换</li><li>只有旧版的浏览器支持</li><li>无法读取<code>reponse</code>的返回值</li></ul><h2 id="img-src" tabindex="-1">img.src <a class="header-anchor" href="#img-src" aria-label="Permalink to &quot;img.src&quot;">​</a></h2><p>创建一个<code>&lt;img&gt;</code>元素，并设置<code>src</code>。大部分的浏览器，都会延迟卸载当前页面，优先加载图像。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">var</span><span style="color:#A6ACCD;"> data </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> JSON</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">stringify</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">   </span><span style="color:#F07178;">time</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> performance</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">now</span><span style="color:#A6ACCD;">()</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span></span>
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> img </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">new</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Image</span><span style="color:#A6ACCD;">()</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">img</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">src </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">`</span><span style="color:#C3E88D;">http://api.wangxiaokai.vip/test?</span><span style="color:#89DDFF;">${</span><span style="color:#A6ACCD;">JSON</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">stringify</span><span style="color:#A6ACCD;">(data)</span><span style="color:#89DDFF;">}`</span><span style="color:#89DDFF;">;</span></span></code></pre></div><h3 id="缺点" tabindex="-1"><strong>缺点</strong> <a class="header-anchor" href="#缺点" aria-label="Permalink to &quot;**缺点**&quot;">​</a></h3><ul><li>数据传输不可靠，有可能浏览器卸载当前页面，直接杀掉图像请求</li><li>只能发起<code>GET</code>请求</li><li>数据大小有限制</li></ul><h2 id="navigator-sendbeacon" tabindex="-1">navigator.sendBeacon <a class="header-anchor" href="#navigator-sendbeacon" aria-label="Permalink to &quot;navigator.sendBeacon&quot;">​</a></h2><p>通过<code>HTTP POST</code>请求，将少量数据使用<code>异步</code>的方式，发送到服务端。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">reportEvent</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">url</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">http://api.wangxiaokai.vip/test</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;"> </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">data</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">JSON</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">stringify</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">   time</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">performance</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">now</span><span style="color:#F07178;">()</span></span>
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;"> </span></span>
<span class="line"><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">navigator</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">sendBeacon</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">url</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">data</span><span style="color:#F07178;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">addEventListener</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">visibilitychange</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;font-style:italic;">if</span><span style="color:#F07178;"> (</span><span style="color:#A6ACCD;">document</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">visiblityState</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">===</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">hidden</span><span style="color:#89DDFF;">&#39;</span><span style="color:#F07178;">) </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">   </span><span style="color:#82AAFF;">reportEvent</span><span style="color:#F07178;">()</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span></code></pre></div><h3 id="发送的时机" tabindex="-1"><strong>发送的时机</strong> <a class="header-anchor" href="#发送的时机" aria-label="Permalink to &quot;**发送的时机**&quot;">​</a></h3><p>浏览器端自动判断合适的时机进行发送</p><h3 id="是否会产生阻塞或影响页面性能" tabindex="-1"><strong>是否会产生阻塞或影响页面性能？</strong> <a class="header-anchor" href="#是否会产生阻塞或影响页面性能" aria-label="Permalink to &quot;**是否会产生阻塞或影响页面性能？**&quot;">​</a></h3><ul><li>不会产生阻塞，影响当前页面的卸载。</li><li>不影响下个新页面的加载，不存在性能问题。</li><li>另外，数据传输可靠。</li></ul><h3 id="语法" tabindex="-1"><strong>语法</strong> <a class="header-anchor" href="#语法" aria-label="Permalink to &quot;**语法**&quot;">​</a></h3><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">navigator</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">sendBeacon</span><span style="color:#A6ACCD;">(url)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">navigator</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">sendBeacon</span><span style="color:#A6ACCD;">(url</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> data)</span><span style="color:#89DDFF;">;</span></span></code></pre></div><h3 id="参数解析" tabindex="-1"><strong>参数解析</strong> <a class="header-anchor" href="#参数解析" aria-label="Permalink to &quot;**参数解析**&quot;">​</a></h3><ul><li><code>url</code>：接收请求的网络地址</li><li><code>data</code>：请求中携带的数据，数据格式可选：<code>ArrayBuffer</code>，<code>ArrayBufferView</code>，<code>Blob</code>，<code>DomString</code>，<code>FormData</code>，<code>URLSearchParams</code></li></ul><h3 id="返回值" tabindex="-1"><strong>返回值</strong> <a class="header-anchor" href="#返回值" aria-label="Permalink to &quot;**返回值**&quot;">​</a></h3><p>当浏览器将数据成功<strong>加入传输队列</strong>时，<code>sendBeacon</code>方法会返回<code>true</code>，否则返回<code>false</code>。</p><blockquote><p>注意返回值的时机：成功加入传输队列，而不是服务端的处理成功后的返回。</p></blockquote><h3 id="缺点-1" tabindex="-1"><strong>缺点</strong> <a class="header-anchor" href="#缺点-1" aria-label="Permalink to &quot;**缺点**&quot;">​</a></h3><ul><li>只能发起<code>POST</code>请求</li><li>无法自定义请求头参数</li><li>数据大小有限制 （Chrome限制大小为<code>64kb</code>）</li><li>只能在window事件<code>visibilitychange</code>和<code>beforeunload</code>中使用，其他事件中回调，会丢失数据。</li></ul><h3 id="兼容性" tabindex="-1">兼容性 <a class="header-anchor" href="#兼容性" aria-label="Permalink to &quot;兼容性&quot;">​</a></h3><p><img src="https://mmbiz.qpic.cn/mmbiz/pfCCZhlbMQSSSpguQyeH8Z7iaDrp4LrM69p9gR5RUUv9NyIqQoKdMhPR3huiaunKGtWAicLWaYM8eoGNPTherJL0A/640?wx_fmt=jpeg&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><h2 id="fetch-keepalive" tabindex="-1">fetch keepalive <a class="header-anchor" href="#fetch-keepalive" aria-label="Permalink to &quot;fetch keepalive&quot;">​</a></h2><p>MDN web docs的描述如下 ：</p><blockquote><p>The <code>keepalive</code> option can be used to allow the request to outlive the page. Fetch with the <code>keepalive</code> flag is a replacement for the <strong><code>Navigator.sendBeacon()</code></strong>[3] API.</p></blockquote><p>标记<code>keepalive</code>的<code>fetch</code>请求允许在页面卸载后执行。</p><div class="language-js"><button title="Copy Code" class="copy"></button><span class="lang">js</span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> url </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">http://api.wangxiaokai.vip/test</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> data </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> JSON</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">stringify</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">   </span><span style="color:#F07178;">time</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> performance</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">now</span><span style="color:#A6ACCD;">()</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span></span>
<span class="line"><span style="color:#82AAFF;">fetch</span><span style="color:#A6ACCD;">(url</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">method</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">POST</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">body</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> data</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">headers</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">&#39;</span><span style="color:#F07178;">Content-Type</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">application/json</span><span style="color:#89DDFF;">&#39;</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#A6ACCD;"> </span><span style="color:#F07178;">keepalive</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#FF9CAC;">true</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">;</span></span></code></pre></div><h1 id="前端开发者的专业度自查-100-条" tabindex="-1">前端开发者的专业度自查 100 条 <a class="header-anchor" href="#前端开发者的专业度自查-100-条" aria-label="Permalink to &quot;前端开发者的专业度自查 100 条&quot;">​</a></h1><ul><li>在需求早期沟通阶段，就能够快速、初略评估出技术路线、工作量、风险点，乃至研发排期</li><li>能够有效识别需求优先级，评估价值</li><li>对不合理的需求会说 NO</li><li>接受任何需求信息、变更，及时同步给必要的相关人士</li><li>无论大小工作，都做系分，大需求大系分，小需求小系分，不限体裁，注重实效</li><li>主动组织系分评审会，知道该邀请哪些相关人士参加</li><li>掌握必要的绘图技能，一图胜千言</li><li>规范制定前后端接口定义</li><li>使用规范的脚手架</li><li>使用规范的研发流程</li><li>代码目录清晰合理，无无效文件</li><li>代码中无 lint 错误</li><li>无错别字，无拼写错误，无多余文字</li><li>变量命名字斟句酌，反复推敲</li><li>代码实现惜字如金，通俗易懂</li><li>代码是给别人看的</li><li>足够的注释</li><li>代码中有必要的单测</li><li>不提交无效文件、临时代码、半成品代码</li><li>撰写优质的 commit msg</li><li>撰写端到端自测用例，并自己完成自测</li><li>撰写完备、清晰的提测邮件</li><li>主动协助测试同学，提供必要帮助</li><li>撰写发布计划，评估发布风险</li><li>灰度发布，关注相关监控指标，用户舆情</li><li>做线上回归自测</li><li>及时通知相关方业务发布进展</li><li>确保自己的业务功能有有效的监控报警、反馈渠道</li><li>能够有效识别会议优先级，评估价值</li><li>参加必须参加的会议</li><li>不参加不必须的会议</li><li>参加的会议全情投入，积极思索，主动发言，拒绝打酱油</li><li>做会议纪要</li><li>分享会议纪要给与会人员</li><li>不参加的会议如有必要，仍主动索取相关会议信息</li><li>善用钉钉等同步交流工具，掌握同步交流的技巧</li><li>善用语雀、github 等异步交流工具，掌握异步交流的技巧</li><li>认真做 code review，写 comments，不做【一键通过侠】</li><li>会熟练并习惯使用 3-4 种任务、项目管理工具</li><li>有自驱力</li><li>有好奇心</li><li>有同理心</li><li>有不屈的意志</li><li>有灵活的身段</li><li>有幽默的语言</li><li>熟练掌握 1-2 门喜闻乐见的游戏</li><li>接受别人交代的任务或需求，会用自己的语言组织并复述，双方意见一致</li><li>做事情事事有回响，件件有进展</li><li>一杆到底，责无旁贷</li><li>交代别人的事，确保对方能够用自己的语言组织并复述，双方意见一致</li><li>关注进度，不做甩手掌柜</li><li>对二手信息、二手需求保持警惕，尽量访问一手信息，追本溯源</li><li>会用正确的姿势鼓励人</li><li>会用正确的姿势赞美人</li><li>会用正确的姿势批评人</li><li>会及时有效的帮助人</li><li>认真写周报</li><li>认真写项目总结、复盘</li><li>认真做年度规划、季度规划</li><li>定期自我反思</li><li>技术上的沉淀写成文章，并分享给别人</li><li>业务上的沉淀写成文章，并分享给别人</li><li>自己的所思所考写成文章，并分享给别人</li><li>保持对前沿动态的敏感度、好奇心</li><li>远离网红</li><li>不要只懂一点点后端，至少两点点</li><li>不要只懂一点点架构，至少两点点</li><li>看书</li><li>《代码整洁之道》一定要看</li><li>坚持系统性、持续性的学习</li><li>掌握必要的方法论</li><li>有端到端的、全链路的意识和视野</li><li>为端到端的、全链路的结果负责</li><li>主动参加必要的业务规划会议或索取必要的信息</li><li>主动、定期与业务 KP 进行单独沟通</li><li>对业务的细节了如指掌</li><li>对业务的规划了然于胸</li><li>对业务有自己的独立见解</li><li>对业务发展能够提出自己的有价值建议</li><li>在业务的高压下，可以坚守职业的底线</li><li>在业务的发展中，可以发现技术的机会</li><li>读开源好代码</li><li>善用各种各样的工具、脚本提升自己的产能</li><li>自己研发各种各样的工具、脚本</li><li>分享自己研发各种各样的工具、脚本</li><li>【真正】喜欢的技术或东西，挤时间也要做，不用【业务忙】做挡箭牌</li><li>业务结果是给公司的，能力成长是给自己的，共同进步是给大家的</li><li>我为人人，才能人人为我</li><li>大家好才是真的好</li><li>写文档，结构清晰，提供挈领</li><li>写文档，排版整齐，干净利落</li><li>写文档，拒绝任何错别字，拒绝任何错别字，拒绝任何错别字</li><li>要谦虚</li><li>要正直</li><li>工作开心</li><li>信任你的同事</li><li>笑脸接客</li><li>以礼待人</li></ul><h1 id="程序员做不好哪些事情容易被开除" tabindex="-1">程序员做不好哪些事情容易被开除 <a class="header-anchor" href="#程序员做不好哪些事情容易被开除" aria-label="Permalink to &quot;程序员做不好哪些事情容易被开除&quot;">​</a></h1><h2 id="看不懂需求和代码" tabindex="-1">看不懂需求和代码 <a class="header-anchor" href="#看不懂需求和代码" aria-label="Permalink to &quot;看不懂需求和代码&quot;">​</a></h2><p>首先要说明的是，看不懂别人写的业务代码是很正常的，因为这块代码要做什么、它的背景是什么，你完全不知道，可能已经被人改了几十次了，逻辑分支早已混乱不堪，你一个新人看不懂很正常。</p><p>还有就是新人刚开始工作的时候，可能会有需求理解不到位、需求漏做、拖延上线等等问题，这些都很常见。</p><p>那么，新人怎么才能快速理解需求并且写好代码呢？这里分两方面来说。</p><h3 id="_1、如何更好的理解需求" tabindex="-1">1、如何更好的理解需求 <a class="header-anchor" href="#_1、如何更好的理解需求" aria-label="Permalink to &quot;1、如何更好的理解需求&quot;">​</a></h3><p><strong>首先是做好沟通</strong>，一些基本的概念性问题，你可以先问问有没有相关的文档可以看，然后再自己去网上搜一搜，最后可以选择去问问产品经理或者项目经理；</p><p>如果实在是一些历史包袱比较重的需求，建议你让产品经理或者项目经理把整个来龙去脉给你讲明白。</p><p><strong>可能有的人会羞于问问题，其实大家讨厌的不是提问的人，而是讨厌伸手党和重复问一个问题的人，没有人会讨厌认真的人。</strong></p><p><strong>然后是，做好需求的拆分。</strong> 刚入职的人一定要做好需求功能点的拆分，比如说让你做一个网页，那你可以拆分好这个页面分为哪几个部分，有哪些可以封装成组件，又有哪些部分是可能你搞不定需要去github找的，这些问题都想清楚了，写代码的思路会非常清晰，也不容易发生需求漏做和排期不准确的情况。</p><h3 id="_2、如何更好的写代码" tabindex="-1">2、如何更好的写代码 <a class="header-anchor" href="#_2、如何更好的写代码" aria-label="Permalink to &quot;2、如何更好的写代码&quot;">​</a></h3><p>可能自己平时做练习的时候很简单，但是到了公司里面一个项目就几万行代码，看起来很费劲，写起来更费劲，这里有几个技巧可以借鉴。</p><p><strong>首先是把握好主脉路即可，放弃细枝末节。</strong></p><p>代码千千万，如果一行一行的看那肯定是看到下个月也看不完，我们看项目重点看这几部分（以前端项目为例）：</p><ol><li>项目的依赖</li><li>项目如何启动</li><li>项目的入口文件</li><li>项目的路由文件</li><li>项目的状态管理文件</li><li>...</li></ol><p>这几部分看完了，基本上一个项目的大致你就明白了</p><p><strong>然后是，debug是熟悉项目最快的方式</strong></p><p>如果你想快速熟悉一个项目，那么我觉得最快的方式就是你去解决几个bug，因为解决bug是一种主动的、带着问题去看项目的一种方式，在解决bug的过程中你不得不深入某些逻辑分支，你也不得不去做调试、看日志等等，不知不觉中，你就熟悉了项目。</p><p>总之，理解好需求、写好代码，是不会被开除的第一步。</p><h2 id="git不熟练" tabindex="-1">GIT不熟练 <a class="header-anchor" href="#git不熟练" aria-label="Permalink to &quot;GIT不熟练&quot;">​</a></h2><p>git这个问题应该是个经典问题，群里的小伙伴最近找到工作的，多多少少都问过我git相关的东西</p><p>git用的不熟练，可能会遇到以下问题：</p><ol><li>仓库都给你半天了，你代码还没拉下来，耽误项目进度</li><li>写好的代码推不到仓库里去，耽误项目进度</li><li>和同事在同一个需求上开发，多分支出现冲突不知道怎么解决，耽误别人的工作时间，甚至把别人写的代码弄没了</li><li>不会合并代码，或者合代码的时候出错</li></ol><p>这些git使用问题，看你自己做自己的项目或者在培训班做项目的时候，很难遇到，但是工作中你需要的别人配合了，你们是一个小团队做协同开发，不懂git或者git命令不熟练，那你的工作很难做得好。</p><p>所以，git不熟练可能会被开除，那你至少应该熟练掌握哪些git知识才能避免试用期就被开除呢？</p><p>我觉得有以下这些：</p><ol><li>如何配置ssh key</li><li>如何clone仓库</li><li>如何新建并切换分支</li><li>如何保存本地的代码并且提交commit到自己的分支</li><li>如何push commit到远程仓库</li><li>如何向主分支提交pr</li><li>如何merge代码，注意这里你需要了解一下merge和rebase的区别</li><li>如何解决代码冲突</li></ol><p>当然了这些问题也不是说你一下子就能全都掌握的，感兴趣可以进群讨论，总之熟练的掌握git你将更好的工作，避免被开除。</p><h2 id="不懂联调" tabindex="-1">不懂联调 <a class="header-anchor" href="#不懂联调" aria-label="Permalink to &quot;不懂联调&quot;">​</a></h2><p>这个问题也很常见，大部分人工作前都是单打独斗，真正在工作中和后端联调的时候，开始慌了，其实注意以下几点就好了（以前端为例）。</p><p>找后端要联调环境地址</p><blockquote><p>所谓联调就是，后端在某个服务器上面起一个服务，然后你去调用ta的接口，来验证整个流程是否可以走通。联调的时候首先是需要后端给你一个联调环境的地址，然后你把请求发送到联调服务器上去，就是这么简单。</p></blockquote><p>优先调主流程</p><blockquote><p>联调的时候不要把时间浪费在细枝末节上，尽量多把时间花费在主流程的调通上，比如说你做了一个保存的功能，那最重要的就是保存流程的走通，至于什么选项多了少了之类的，都不重要。</p></blockquote><p>接口质量太差，可以找后端battle</p><blockquote><p>有时候联调的时候发现后端的接口10个里面有5个都是不通的，一调就报500错误，那你就别浪费时间了，让后端自己用postman把接口调通了再给你。</p></blockquote><p>职场里面虽然大家都应该保持和气，但是必要的battle还是需要的。做好联调，避免被开除。</p><h2 id="不懂怎么上线" tabindex="-1">不懂怎么上线 <a class="header-anchor" href="#不懂怎么上线" aria-label="Permalink to &quot;不懂怎么上线&quot;">​</a></h2><p>不同公司的上线流程不一样，很多大公司的上线流程基本都可视化了，就用鼠标点一点就上线了，这里着重讲讲在小公司该怎么办（以前端为例），好像群里有粉丝反馈这里不会。</p><ol><li>首先你需要把项目打包好</li><li>把打包后的文件上传到服务器的指定文件夹</li><li>配置好接口的转发，一般是配置nginx</li><li>重启server</li></ol><p>这里面你需要这些知识：</p><ol><li>基本的linux命令，比如上传文件到指定服务器等等</li><li>基本的nginx知识，比如配置文件、重启等等</li><li>掌握好这些知识，也可以避免被开除。</li></ol><h1 id="接私活平台⭐" tabindex="-1">接私活平台⭐ <a class="header-anchor" href="#接私活平台⭐" aria-label="Permalink to &quot;接私活平台⭐&quot;">​</a></h1><h2 id="什么样的私活不能接" tabindex="-1">什么样的私活不能接 <a class="header-anchor" href="#什么样的私活不能接" aria-label="Permalink to &quot;什么样的私活不能接&quot;">​</a></h2><p>1、没有第三方担保的个人对个人的尽量不要接，双方都没保障，出了问题很大的可能撕破脸皮不了了之。</p><p>2、一上来就直接说给我开发一个什么软件，不说具体需求，没有需求文档的都不靠谱，这样的项目不要接。</p><p>3、尽量442收费方式，即开工收40%项目款，项目中期收40%项目款，项目结束收20%项目款。一开始不给钱的，尽量不要接，这一点一定要记住，否则很容易付出了劳动得不到应得的收入。</p><p>不给完钱，不交完整代码。你的成果就是代码，如果没给完钱，就把代码交给了对方，也容易被坑到。</p><h2 id="国内远程工作平台-接单平台" tabindex="-1">国内远程工作平台，接单平台 <a class="header-anchor" href="#国内远程工作平台-接单平台" aria-label="Permalink to &quot;国内远程工作平台，接单平台&quot;">​</a></h2><h3 id="_1、coding-码市" tabindex="-1">1、CODING 码市 <a class="header-anchor" href="#_1、coding-码市" aria-label="Permalink to &quot;1、CODING 码市&quot;">​</a></h3><p><strong>官方网站：<a href="https://mart.coding.net" target="_blank" rel="noreferrer">https://mart.coding.net</a></strong></p><p>著名的Coding旗下的互联网软件外包服务平台，平台以外包为主。</p><h3 id="_2、-开源众包" tabindex="-1">2、 开源众包 <a class="header-anchor" href="#_2、-开源众包" aria-label="Permalink to &quot;2、 开源众包&quot;">​</a></h3><p><strong>官方网站：<a href="https://zb.oschina.net/projects/list.html" target="_blank" rel="noreferrer">https://zb.oschina.net/projects/list.html</a></strong></p><p>开源中国的众包平台，主要是以众包为主。</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.12.30/202211241743703.png" alt="image-20221124174327567" style="zoom:80%;"><p><strong>什么是软件众包</strong></p><p>目前软件众包分为简单任务和复杂任务，简单软件众包的任务可以由个人来承担，比较复杂的软件可以同时协同多人完成的任务</p><p>它的流程是：首先发包人对任务进行细分，分解到最小后，然后分包出去，按照各自的能力和知识水平领包，最后完成任务，发包人通过审核通过之后，项目才算完成。</p><h3 id="_3、猪八戒" tabindex="-1">3、猪八戒 <a class="header-anchor" href="#_3、猪八戒" aria-label="Permalink to &quot;3、猪八戒&quot;">​</a></h3><p><strong>官方网站：<a href="https://zbj.com" target="_blank" rel="noreferrer">https://zbj.com</a></strong></p><p>找兼职的地方，主要是入门级项目，不适合专业程序员，上面各类需求发布都有不限于软件开发行业，更适合新手。</p><p><img src="https://mmbiz.qpic.cn/mmbiz_jpg/WwPkUCFX4x7RXV2owe3IFUL0XHShicWORot1Xr4arqm1b9ibZ0IBXr5zxLYFWSib98RoxmE6PvoKmXF2BfSH6PNrg/640?wx_fmt=jpeg&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><h3 id="_4、程序员客栈" tabindex="-1">4、程序员客栈 <a class="header-anchor" href="#_4、程序员客栈" aria-label="Permalink to &quot;4、程序员客栈&quot;">​</a></h3><p><strong>官方网站：<a href="https://www.proginn.com" target="_blank" rel="noreferrer">https://www.proginn.com</a></strong></p><p>程序员，产品经理，设计师等互联网相关人员，都能在上面找到适合自己的项目。支持自由、远程和兼职工作，还可以按需雇佣，工作模式非常多 。</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.12.30/202211241744495.png" alt="image-20221124174402359" style="zoom:80%;"><h3 id="_5、英选" tabindex="-1">5、英选 <a class="header-anchor" href="#_5、英选" aria-label="Permalink to &quot;5、英选&quot;">​</a></h3><p><strong>官方网站：<a href="http://linktion.cn" target="_blank" rel="noreferrer">http://linktion.cn</a></strong></p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.12.30/202211241744658.png" alt="image-20221124174422555" style="zoom:80%;"><p>虽然是外部平台，当他们还是针对外部项目的一些长期令人诟病的问题进行了一些优化，如下图：</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.12.30/202211241744812.png" alt="image-20221124174437747" style="zoom:80%;"><h3 id="_6-开发邦" tabindex="-1">6. 开发邦 <a class="header-anchor" href="#_6-开发邦" aria-label="Permalink to &quot;6. 开发邦&quot;">​</a></h3><p><strong>官方网站：<a href="http://www.kaifabang.com" target="_blank" rel="noreferrer">http://www.kaifabang.com</a></strong></p><p>特点：服务范围明确，IT开发项目垂直度高，能吸引到一部分需求明确的客户。</p><p>微信搜索公众号：前端技术编程，回复：前端 领取资料 。</p><p>平台也致力于利用互联网软件技术为客户提高效率、降低成本、提升效能、优化管理。</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.12.30/202211241744105.png" alt="image-20221124174453996" style="zoom:80%;"><h3 id="_7、猿急送" tabindex="-1">7、猿急送 <a class="header-anchor" href="#_7、猿急送" aria-label="Permalink to &quot;7、猿急送&quot;">​</a></h3><p><strong>官方网站：<a href="https://www.yuanjisong.com/" target="_blank" rel="noreferrer">https://www.yuanjisong.com/</a></strong></p><p>平台特点：追求高质量的雇主和工程师，汇聚了知名互联网公司的技术、设计、产品大牛，通过实际坐班、远程等方式，一对一为创业公司解决问题，提高创业效率。</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.12.30/202211241745078.png" alt="image-20221124174509980" style="zoom:80%;"><h3 id="_8、人人开发" tabindex="-1">8、人人开发 <a class="header-anchor" href="#_8、人人开发" aria-label="Permalink to &quot;8、人人开发&quot;">​</a></h3><p><strong>官方网站：<a href="http://rrkf.com" target="_blank" rel="noreferrer">http://rrkf.com</a></strong></p><p>基于可视化快速开发平台 - 捷得(Joget)/捷得云(Joget Cloud)(PaaS),集众多开发者资源,为企业提供企业管理软件服务</p><p><img src="https://mmbiz.qpic.cn/mmbiz_jpg/WwPkUCFX4x7RXV2owe3IFUL0XHShicWORiahwy1xfU8oeQhw6EIMvobchkficicr20vHvm24LicFYKociaGEwxGqNMpg/640?wx_fmt=jpeg&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.12.30/202211241745936.png" alt="image-20221124174535851" style="zoom:80%;"><h2 id="国外远程工作平台" tabindex="-1">国外远程工作平台 <a class="header-anchor" href="#国外远程工作平台" aria-label="Permalink to &quot;国外远程工作平台&quot;">​</a></h2><h3 id="_1、-freelancer" tabindex="-1">1、 Freelancer <a class="header-anchor" href="#_1、-freelancer" aria-label="Permalink to &quot;1、 Freelancer&quot;">​</a></h3><p><strong>官方网站：<a href="https://www.freelance.com/" target="_blank" rel="noreferrer">https://www.freelance.com/</a></strong></p><p>工作类型主要覆盖了程序开发到市场营销、广告、会计等一系列的可以远程的工作。</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2022.12.30/202211241745288.png" alt="image-20221124174550147" style="zoom:80%;"><h3 id="_2、stackoverflow" tabindex="-1">2、Stackoverflow <a class="header-anchor" href="#_2、stackoverflow" aria-label="Permalink to &quot;2、Stackoverflow&quot;">​</a></h3><p><strong>官方网站：<a href="https://stackoverflow.com/jobs" target="_blank" rel="noreferrer">https://stackoverflow.com/jobs</a></strong></p><p><img src="https://mmbiz.qpic.cn/mmbiz_jpg/WwPkUCFX4x7RXV2owe3IFUL0XHShicWORTLL4b6fUgynx9yOQicQhgWQHRPkXVicEPksl3qyam5YkzD722Nj9KhBA/640?wx_fmt=jpeg&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>Stackoverflow 是程序员非常热爱的一个社区，但是其本身就为程序员提供了远程工作的服务，Stackoverflow Jobs 里有远程职位的筛选，这里有丰富的远程技术职位。相Freelancer 更容易被程序员接受。</p><h2 id="双方信息对称很重要-诚信为本" tabindex="-1">双方信息对称很重要，诚信为本 <a class="header-anchor" href="#双方信息对称很重要-诚信为本" aria-label="Permalink to &quot;双方信息对称很重要，诚信为本&quot;">​</a></h2><p>1、一些私活多数是远程工作，这要求双方在需求沟通过程中信息能对称，特别作为乙方的程序员，需要培养自己良好的沟通能力，这样能减少因需求不明确导致的设计频繁修改，项目延期等问题，提高项目交付效率，建立信任关系。</p><p>2、目前程序员私活的市场现状是僧多肉少，在接单过程中很可能遇到同行竞争压价（一些工作室长期接单，积累大量框架模板，能比个人快很多的速度交付，通过降低开发成本，压低市场价格，另外一方面后续他们也会通过一些手段赚取客户更多，比如：收取相对高额的售后费用，骗取基于创业的小白缴纳一些系统加盟费之类的。</p><p>最好选择一到二个平台长期经营，能在本地找到长期合作方建立信任关系是最好。</p><p><strong>写在最后</strong></p><p>接私活会占用你大量的业余时间，所以是否应该接私活，自己一定要慎重考虑一下，毕竟，业余时间也是提升你自己的时间。也不是说不要接，可以尽可能的接一些能对自己有提升的项目，比如该项目中大部分东西你都没问题，但是小部分技术，还需要自己去学习一下，才可以搞定。这种项目其实是最好的，既赚了外快，也提升了自己。不建议接那种对自己没有挑战的私活，可以把业余时间放到提升自己技术上面，从而为以后找到更好的工作。</p><h1 id="spa-vs-mpa-vs-pwa" tabindex="-1">SPA vs MPA vs PWA <a class="header-anchor" href="#spa-vs-mpa-vs-pwa" aria-label="Permalink to &quot;SPA vs MPA vs PWA&quot;">​</a></h1><p>今天来看三个重要的概念：SPA、MPA、PWA。</p><h2 id="_1-单页面应用程序-spa" tabindex="-1">1. 单页面应用程序（SPA） <a class="header-anchor" href="#_1-单页面应用程序-spa" aria-label="Permalink to &quot;1. 单页面应用程序（SPA）&quot;">​</a></h2><blockquote><p>SPA 全称为 Single-Page Application，表示单页面应用程序。在单页面应用程序中，我们不会为每个路径创建多个 HTML 文件，而是使用 JavaScript 为同一页面上的不同路径呈现不同的组件。当从浏览器请求单页面应用程序时，就会下载一个bundle.js文件，该文件包含所有请求网站的已编译 JavaScript 代码。使用这种方法，浏览器会通过使用 HTML5 History API 根据用户选择的路径呈现单个页面。</p></blockquote><blockquote><p>如果网站使用了延迟加载，那么可能会有多个bundle.js文件会根据请求的路径进行下载。因此，除了特殊情况，否则不会重新加载页面（再次从服务器请求）。如果想维护应用程序的状态，这一点是非常重要的，因为重新刷新页面就会重置应用程序的状态。</p></blockquote><h4 id="☀-spa-优点" tabindex="-1">☀ SPA 优点 <a class="header-anchor" href="#☀-spa-优点" aria-label="Permalink to &quot;☀ SPA 优点&quot;">​</a></h4><ul><li>**提高页面加载速度，从而获得更好的用户体验：**它们通常只加载一次。加载后，页面渲染取决于浏览器的速度。</li><li>**更少的服务器负载：**渲染逻辑在浏览器中执行。服务器和客户端之间只发送相关数据。</li><li>**缓存：**只向服务器发送一次请求，返回的响应会被缓存，也可以离线使用SPA。</li><li><strong>调试：</strong> React 和 Vue 等 SPA 框架提供了调试工具，这使开发人员的开发调试更加轻松。</li><li>**代码可重用性：**开发人员可以重用代码，这使得开发效率更高。</li><li>**转场动画：**容易实现。</li><li><strong>页面间数据传递</strong>：因为在一个页面内，所以页面之间数据传递很容易</li></ul><h4 id="☀-spa-缺点" tabindex="-1">☀ SPA 缺点 <a class="header-anchor" href="#☀-spa-缺点" aria-label="Permalink to &quot;☀ SPA 缺点&quot;">​</a></h4><ul><li>**搜索引擎优化 (SEO) 较差：**搜索引擎具有可以解析 JavaScript 的爬虫，但它们很难爬取异步内容。加载初始页面后，不知道还有其他数据的爬虫将停止爬取，从而导致 SEO 效率低。</li><li>**内存泄漏：**事件监听器占用大量空间。使用 SPA 在客户端很容易引入内存泄漏，如果将事件侦听器添加到全局对象，而没有在卸载组件时删除它们，就会产生内存泄漏。如果不想导致内存泄漏，则需要清理事件侦听器、定时器等。</li><li>**安全性：**与 MPA 相比，SPA更容易受到跨站点脚本攻击（XSS）。</li></ul><h2 id="_2-多页面应用程序-mpa" tabindex="-1">2. 多页面应用程序（MPA） <a class="header-anchor" href="#_2-多页面应用程序-mpa" aria-label="Permalink to &quot;2. 多页面应用程序（MPA）&quot;">​</a></h2><p>MPA 全称 Multi-Page Application，表示多页面应用程序。多页面应用程序由多个 HTML 文件组成，每当请求页面时就会下载这些文件。我们在地址栏输入的每个新的 URL 或单击的每个超链接时都会向服务器发送一个新请求，并下载一个新的页面。在这种方法中，服务器完成了较为繁重的工作。因此，如果用户的网络连接较差，每个页面可能需要很长时间才能加载出来。</p><h4 id="☀-mpa-优点" tabindex="-1">☀ MPA 优点 <a class="header-anchor" href="#☀-mpa-优点" aria-label="Permalink to &quot;☀ MPA 优点&quot;">​</a></h4><ul><li>**搜索引擎优化（SEO）更好：**单页可以只有有限数量的关键字，但多页应用程序可以为多个页面提供相同数量的关键字，这为爬虫提供了更多关于网站的信息.</li><li>**良好的可扩展性：**可以持续添加功能，不断扩展。但在 SPA 中，随着不断添加功能，bundle.js 将会不断增长，因此要么减少内容，要么进行延迟加载。</li><li>**内存泄漏很少见：**服务器端很有可能出现内存泄漏，但客户端内存泄漏很少见，因为浏览器将为每个导航链接加载不同的脚本。</li></ul><h4 id="☀mpa-缺点" tabindex="-1">☀MPA 缺点 <a class="header-anchor" href="#☀mpa-缺点" aria-label="Permalink to &quot;☀MPA 缺点&quot;">​</a></h4><ul><li>**加载速度慢：**它们不断地为每个请求加载新页面（即使 UI 发生了细微的变化，页面也必须重新加载）。如果客户端的网络连接不好或服务器速度慢，加载速度就会下降，最终导致用户体验不佳。</li><li>**开发效率低：**代码可重用性较低，文件较大，前端与后端的耦合更紧密。这些因素会使开发效率低。</li><li>**增加服务器负载：**与服务器的每次交互都包含一个需要渲染的 UI 包。</li><li>**转场动画：**无法实现。</li><li><strong>页面间数据传递</strong>：依赖URL、Cookie、或者localStorage等，实现麻烦。</li></ul><h2 id="_3-渐进式应用程序-pwa" tabindex="-1">3. 渐进式应用程序（PWA） <a class="header-anchor" href="#_3-渐进式应用程序-pwa" aria-label="Permalink to &quot;3. 渐进式应用程序（PWA）&quot;">​</a></h2><p>PWA 全称 Progressive Web Apps，表示渐进式应用程序。渐进式应用程序可以在独立的窗口中运行，而不是在浏览器的选项卡中运行。简单的说，它们是一种web应用程序，类似于本地应用程序，可以安装在手机、平板电脑或者笔记本电脑上。下载后，用户可以通过屏幕上的图标访问该应用。这种应用还可以向用户发送推送消息和通知。渐进式应用程序可以是 单页面应用（SPA）也可以是多页面应用（MPA）。</p><p>想要申请 PWA 应用，必须满足三个条件：</p><ol><li><strong>安全上下文 (HTTPS)：</strong> 安全上下文是为用户身份验证和机密性定义的最低标准。PWA 的许多 API 和许多功能（如地理定位）只有在应用程序通过安全网络提供服务时才可用。</li><li><strong>Service Worker：</strong> Service Worker 是在后台运行并控制浏览器如何处理网络请求和内容缓存的脚本。PWA 通过服务工作者提供离线服务。</li><li>**清单文件：**这是一个 JSON 文件，用于保存 PWA 所需的应用程序信息，例如应用程序的名称、启动 URL、多种尺寸的图标和主题颜色。</li></ol><p>与原生移动应用程序相比，渐进式 Web 应用程序更小。研究表明它们有助于增加流量和用户参与度，并降低跳出率，这主要归功于它的离线可用性。</p><h1 id="必备基础英文单词" tabindex="-1">必备基础英文单词 <a class="header-anchor" href="#必备基础英文单词" aria-label="Permalink to &quot;必备基础英文单词&quot;">​</a></h1><p>在前端开发过程中，掌握一些常见英语词汇是必要的，今天跟大家分享一些前端常见的英语词汇，供大家参考使用。</p><h2 id="导航类" tabindex="-1">导航类 <a class="header-anchor" href="#导航类" aria-label="Permalink to &quot;导航类&quot;">​</a></h2><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">导航：nav</span></span>
<span class="line"><span style="color:#A6ACCD;">标题：title</span></span>
<span class="line"><span style="color:#A6ACCD;">摘要：summary</span></span>
<span class="line"><span style="color:#A6ACCD;">菜单：menu</span></span>
<span class="line"><span style="color:#A6ACCD;">子菜单：submenu</span></span>
<span class="line"><span style="color:#A6ACCD;">主导航：mainbav</span></span>
<span class="line"><span style="color:#A6ACCD;">子导航：subnav</span></span>
<span class="line"><span style="color:#A6ACCD;">顶导航：topnav</span></span>
<span class="line"><span style="color:#A6ACCD;">边导航：sidebar</span></span>
<span class="line"><span style="color:#A6ACCD;">左导航：leftsidebar</span></span>
<span class="line"><span style="color:#A6ACCD;">右导航：rightsidebar</span></span></code></pre></div><h2 id="页面结构布局" tabindex="-1">页面结构布局 <a class="header-anchor" href="#页面结构布局" aria-label="Permalink to &quot;页面结构布局&quot;">​</a></h2><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">容器：container</span></span>
<span class="line"><span style="color:#A6ACCD;">页头：header</span></span>
<span class="line"><span style="color:#A6ACCD;">内容：content/container</span></span>
<span class="line"><span style="color:#A6ACCD;">页尾：footer</span></span>
<span class="line"><span style="color:#A6ACCD;">导航：nav</span></span>
<span class="line"><span style="color:#A6ACCD;">侧栏：sidebar</span></span>
<span class="line"><span style="color:#A6ACCD;">栏目：column</span></span>
<span class="line"><span style="color:#A6ACCD;">页面主体：main</span></span>
<span class="line"><span style="color:#A6ACCD;">左右中：left right center</span></span>
<span class="line"><span style="color:#A6ACCD;">页面外围控制整体布局宽度：wrapper</span></span></code></pre></div><h2 id="功能" tabindex="-1">功能 <a class="header-anchor" href="#功能" aria-label="Permalink to &quot;功能&quot;">​</a></h2><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">标志：logo</span></span>
<span class="line"><span style="color:#A6ACCD;">滚动：scroll</span></span>
<span class="line"><span style="color:#A6ACCD;">广告：banner</span></span>
<span class="line"><span style="color:#A6ACCD;">登录：login</span></span>
<span class="line"><span style="color:#A6ACCD;">注册：regsiter</span></span>
<span class="line"><span style="color:#A6ACCD;">搜索：search</span></span>
<span class="line"><span style="color:#A6ACCD;">图标：icon</span></span>
<span class="line"><span style="color:#A6ACCD;">注释：note</span></span>
<span class="line"><span style="color:#A6ACCD;">指南：guild</span></span>
<span class="line"><span style="color:#A6ACCD;">状态：status</span></span>
<span class="line"><span style="color:#A6ACCD;">服务：service</span></span>
<span class="line"><span style="color:#A6ACCD;">按钮：btn</span></span>
<span class="line"><span style="color:#A6ACCD;">热点：hot</span></span>
<span class="line"><span style="color:#A6ACCD;">新闻：news</span></span>
<span class="line"><span style="color:#A6ACCD;">下载：download</span></span>
<span class="line"><span style="color:#A6ACCD;">版权：copyright</span></span>
<span class="line"><span style="color:#A6ACCD;">投票：vote</span></span>
<span class="line"><span style="color:#A6ACCD;">标签页：tab</span></span>
<span class="line"><span style="color:#A6ACCD;">登录条：loginbar</span></span>
<span class="line"><span style="color:#A6ACCD;">面包屑：breadCrumb</span></span>
<span class="line"><span style="color:#A6ACCD;">当前的：current</span></span>
<span class="line"><span style="color:#A6ACCD;">小技巧：tips</span></span>
<span class="line"><span style="color:#A6ACCD;">功能区：shop</span></span>
<span class="line"><span style="color:#A6ACCD;">文章列表：list</span></span>
<span class="line"><span style="color:#A6ACCD;">提示信息：msg</span></span>
<span class="line"><span style="color:#A6ACCD;">合作伙伴：partner</span></span>
<span class="line"><span style="color:#A6ACCD;">友情链接：friendlink</span></span></code></pre></div><h2 id="css-英文释译" tabindex="-1">CSS 英文释译 <a class="header-anchor" href="#css-英文释译" aria-label="Permalink to &quot;CSS 英文释译&quot;">​</a></h2><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">线：line</span></span>
<span class="line"><span style="color:#A6ACCD;">行：row</span></span>
<span class="line"><span style="color:#A6ACCD;">宽 ：width</span></span>
<span class="line"><span style="color:#A6ACCD;">高：height</span></span>
<span class="line"><span style="color:#A6ACCD;">外边界：margin</span></span>
<span class="line"><span style="color:#A6ACCD;">内边界：padding</span></span>
<span class="line"><span style="color:#A6ACCD;">边框：border</span></span>
<span class="line"><span style="color:#A6ACCD;">行高：line-height</span></span>
<span class="line"><span style="color:#A6ACCD;">背景：background</span></span>
<span class="line"><span style="color:#A6ACCD;">颜色：color</span></span>
<span class="line"><span style="color:#A6ACCD;">顶部：top</span></span>
<span class="line"><span style="color:#A6ACCD;">标题：title</span></span>
<span class="line"><span style="color:#A6ACCD;">字体：font</span></span>
<span class="line"><span style="color:#A6ACCD;">身体：body</span></span>
<span class="line"><span style="color:#A6ACCD;">大小：size</span></span>
<span class="line"><span style="color:#A6ACCD;">列表：list</span></span>
<span class="line"><span style="color:#A6ACCD;">文本：text</span></span>
<span class="line"><span style="color:#A6ACCD;">样式：style</span></span>
<span class="line"><span style="color:#A6ACCD;">对齐：align</span></span>
<span class="line"><span style="color:#A6ACCD;">图像：image</span></span>
<span class="line"><span style="color:#A6ACCD;">修饰：decoration</span></span>
<span class="line"><span style="color:#A6ACCD;">资源：source</span></span>
<span class="line"><span style="color:#A6ACCD;">宽度：width</span></span>
<span class="line"><span style="color:#A6ACCD;">穿过：through</span></span>
<span class="line"><span style="color:#A6ACCD;">高度：height</span></span>
<span class="line"><span style="color:#A6ACCD;">缩进：indent</span></span>
<span class="line"><span style="color:#A6ACCD;">斜体：italic</span></span>
<span class="line"><span style="color:#A6ACCD;">链接：link</span></span>
<span class="line"><span style="color:#A6ACCD;">加粗：bold</span></span>
<span class="line"><span style="color:#A6ACCD;">斜体：italic</span></span>
<span class="line"><span style="color:#A6ACCD;">加重：weight</span></span>
<span class="line"><span style="color:#A6ACCD;">加粗：bold</span></span>
<span class="line"><span style="color:#A6ACCD;">输入：input</span></span>
<span class="line"><span style="color:#A6ACCD;">主体：main</span></span>
<span class="line"><span style="color:#A6ACCD;">下面的：under</span></span>
<span class="line"><span style="color:#A6ACCD;">重复：repeat</span></span>
<span class="line"><span style="color:#A6ACCD;">填充：padding</span></span>
<span class="line"><span style="color:#A6ACCD;">位置：position</span></span>
<span class="line"><span style="color:#A6ACCD;">正常：normal</span></span>
<span class="line"><span style="color:#A6ACCD;">父级 parent</span></span>
<span class="line"><span style="color:#A6ACCD;">子级：children</span></span>
<span class="line"><span style="color:#A6ACCD;">隐藏：hidden</span></span>
<span class="line"><span style="color:#A6ACCD;">显示：visible</span></span>
<span class="line"><span style="color:#A6ACCD;">溢出：overflow</span></span>
<span class="line"><span style="color:#A6ACCD;">列表：list</span></span>
<span class="line"><span style="color:#A6ACCD;">样式 style</span></span>
<span class="line"><span style="color:#A6ACCD;">导航：nav</span></span>
<span class="line"><span style="color:#A6ACCD;">显示类型：display</span></span>
<span class="line"><span style="color:#A6ACCD;">广告图片：banner</span></span>
<span class="line"><span style="color:#A6ACCD;">页眉：header</span></span></code></pre></div><h2 id="文件命名" tabindex="-1">文件命名 <a class="header-anchor" href="#文件命名" aria-label="Permalink to &quot;文件命名&quot;">​</a></h2><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">主要的：master</span></span>
<span class="line"><span style="color:#A6ACCD;">模块：module</span></span>
<span class="line"><span style="color:#A6ACCD;">重置：reset</span></span>
<span class="line"><span style="color:#A6ACCD;">基本共用：base/common</span></span>
<span class="line"><span style="color:#A6ACCD;">布局，版面：layout</span></span>
<span class="line"><span style="color:#A6ACCD;">主题：themes</span></span>
<span class="line"><span style="color:#A6ACCD;">专栏：columns</span></span>
<span class="line"><span style="color:#A6ACCD;">文字：font</span></span>
<span class="line"><span style="color:#A6ACCD;">表单：forms</span></span>
<span class="line"><span style="color:#A6ACCD;">补丁：mend</span></span>
<span class="line"><span style="color:#A6ACCD;">打印：print</span></span>
<span class="line"><span style="color:#A6ACCD;">混入：mixins</span></span>
<span class="line"><span style="color:#A6ACCD;">组件：components</span></span>
<span class="line"><span style="color:#A6ACCD;">静态资源：public/static</span></span>
<span class="line"><span style="color:#A6ACCD;">路由：router</span></span>
<span class="line"><span style="color:#A6ACCD;">页面/视图: pages/views</span></span>
<span class="line"><span style="color:#A6ACCD;">配置: config</span></span></code></pre></div><h2 id="其他" tabindex="-1">其他 <a class="header-anchor" href="#其他" aria-label="Permalink to &quot;其他&quot;">​</a></h2><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">broswer 浏览器（客户端）</span></span>
<span class="line"><span style="color:#A6ACCD;">html 超文本标记语言</span></span>
<span class="line"><span style="color:#A6ACCD;">css 层叠样式表</span></span>
<span class="line"><span style="color:#A6ACCD;">javascript 语言名字(类似python/php/c…)</span></span>
<span class="line"><span style="color:#A6ACCD;">title 标题</span></span>
<span class="line"><span style="color:#A6ACCD;">body 身体</span></span>
<span class="line"><span style="color:#A6ACCD;">head 头</span></span>
<span class="line"><span style="color:#A6ACCD;">div 盒子(类似收纳箱)</span></span>
<span class="line"><span style="color:#A6ACCD;">font 字体</span></span>
<span class="line"><span style="color:#A6ACCD;">width 宽</span></span>
<span class="line"><span style="color:#A6ACCD;">height 高</span></span>
<span class="line"><span style="color:#A6ACCD;">background 背景</span></span>
<span class="line"><span style="color:#A6ACCD;">color 颜色</span></span>
<span class="line"><span style="color:#A6ACCD;">ul (Unordered List) 无序列表</span></span>
<span class="line"><span style="color:#A6ACCD;">ol (Ordered List) 有序列表</span></span>
<span class="line"><span style="color:#A6ACCD;">li (List Item) 列表项</span></span>
<span class="line"><span style="color:#A6ACCD;">dl (Definition List) 自定义列表</span></span>
<span class="line"><span style="color:#A6ACCD;">form 表单</span></span>
<span class="line"><span style="color:#A6ACCD;">action 地址</span></span>
<span class="line"><span style="color:#A6ACCD;">method 方法</span></span>
<span class="line"><span style="color:#A6ACCD;">input 输入框</span></span>
<span class="line"><span style="color:#A6ACCD;">text 文本</span></span>
<span class="line"><span style="color:#A6ACCD;">password 密码</span></span>
<span class="line"><span style="color:#A6ACCD;">radio 单选</span></span>
<span class="line"><span style="color:#A6ACCD;">checkbox 多选</span></span>
<span class="line"><span style="color:#A6ACCD;">select 下拉菜单</span></span>
<span class="line"><span style="color:#A6ACCD;">option 选项</span></span>
<span class="line"><span style="color:#A6ACCD;">padding 内边距</span></span>
<span class="line"><span style="color:#A6ACCD;">margin 外边距</span></span>
<span class="line"><span style="color:#A6ACCD;">border 边线</span></span>
<span class="line"><span style="color:#A6ACCD;">solid 直线</span></span>
<span class="line"><span style="color:#A6ACCD;">dashed 虚线</span></span>
<span class="line"><span style="color:#A6ACCD;">dotted 点线</span></span>
<span class="line"><span style="color:#A6ACCD;">overflow 溢出</span></span>
<span class="line"><span style="color:#A6ACCD;">hidden 隐藏</span></span>
<span class="line"><span style="color:#A6ACCD;">visibility 可见度</span></span>
<span class="line"><span style="color:#A6ACCD;">table 表格</span></span>
<span class="line"><span style="color:#A6ACCD;">thead 表头</span></span>
<span class="line"><span style="color:#A6ACCD;">tbody 表格内容</span></span>
<span class="line"><span style="color:#A6ACCD;">tr (table row) 行</span></span>
<span class="line"><span style="color:#A6ACCD;">td/th (table data, table headline)列</span></span>
<span class="line"><span style="color:#A6ACCD;">rowspan 合并行</span></span>
<span class="line"><span style="color:#A6ACCD;">colspan 合并列</span></span>
<span class="line"><span style="color:#A6ACCD;">collapse 合并</span></span>
<span class="line"><span style="color:#A6ACCD;">position 定位</span></span>
<span class="line"><span style="color:#A6ACCD;">relative 绝对定位</span></span>
<span class="line"><span style="color:#A6ACCD;">absolute 相对定位</span></span>
<span class="line"><span style="color:#A6ACCD;">fixed 固定定位</span></span>
<span class="line"><span style="color:#A6ACCD;">static 静态定位</span></span>
<span class="line"><span style="color:#A6ACCD;">script 脚本</span></span>
<span class="line"><span style="color:#A6ACCD;">string 字符串</span></span>
<span class="line"><span style="color:#A6ACCD;">number 数字</span></span>
<span class="line"><span style="color:#A6ACCD;">boolean 布尔</span></span>
<span class="line"><span style="color:#A6ACCD;">undefined 未定义</span></span>
<span class="line"><span style="color:#A6ACCD;">null 空(None)</span></span>
<span class="line"><span style="color:#A6ACCD;">function 函数</span></span>
<span class="line"><span style="color:#A6ACCD;">document 文档</span></span>
<span class="line"><span style="color:#A6ACCD;">get 获取</span></span>
<span class="line"><span style="color:#A6ACCD;">element 元素</span></span>
<span class="line"><span style="color:#A6ACCD;">by 通过</span></span>
<span class="line"><span style="color:#A6ACCD;">id id</span></span>
<span class="line"><span style="color:#A6ACCD;">tagName 标签名</span></span>
<span class="line"><span style="color:#A6ACCD;">window 窗口</span></span>
<span class="line"><span style="color:#A6ACCD;">object 对象</span></span>
<span class="line"><span style="color:#A6ACCD;">array 数字(类似python中的list列表)</span></span>
<span class="line"><span style="color:#A6ACCD;">setInterval 定时器</span></span>
<span class="line"><span style="color:#A6ACCD;">clearInterval 清除定时器</span></span>
<span class="line"><span style="color:#A6ACCD;">$ 美元符号</span></span>
<span class="line"><span style="color:#A6ACCD;">next 下一个</span></span>
<span class="line"><span style="color:#A6ACCD;">prev 前一个（previous）</span></span>
<span class="line"><span style="color:#A6ACCD;">parent 父母/双亲</span></span>
<span class="line"><span style="color:#A6ACCD;">children 孩子</span></span>
<span class="line"><span style="color:#A6ACCD;">click 点击</span></span>
<span class="line"><span style="color:#A6ACCD;">mouseleave 鼠标移开</span></span>
<span class="line"><span style="color:#A6ACCD;">mouseenter 鼠标进入</span></span>
<span class="line"><span style="color:#A6ACCD;">animate 动画</span></span>
<span class="line"><span style="color:#A6ACCD;">slide 滑动</span></span>
<span class="line"><span style="color:#A6ACCD;">fade 渐进</span></span>
<span class="line"><span style="color:#A6ACCD;">show 显示</span></span>
<span class="line"><span style="color:#A6ACCD;">hide 隐藏</span></span>
<span class="line"><span style="color:#A6ACCD;">test 测试</span></span>
<span class="line"><span style="color:#A6ACCD;">stopProperation 阻止冒泡</span></span>
<span class="line"><span style="color:#A6ACCD;">preventDefault 阻止默认行为</span></span>
<span class="line"><span style="color:#A6ACCD;">dom document object model 文档对象模型</span></span>
<span class="line"><span style="color:#A6ACCD;">ajax 啊甲克斯</span></span>
<span class="line"><span style="color:#A6ACCD;">type 类型</span></span>
<span class="line"><span style="color:#A6ACCD;">url 统一资源定位符</span></span>
<span class="line"><span style="color:#A6ACCD;">data 数据</span></span>
<span class="line"><span style="color:#A6ACCD;">dataTpye 数据类型</span></span>
<span class="line"><span style="color:#A6ACCD;">success 成功</span></span>
<span class="line"><span style="color:#A6ACCD;">error 失败</span></span>
<span class="line"><span style="color:#A6ACCD;">done 成功</span></span>
<span class="line"><span style="color:#A6ACCD;">fail 失败</span></span>
<span class="line"><span style="color:#A6ACCD;">mustache 胡子</span></span>
<span class="line"><span style="color:#A6ACCD;">computed 计算</span></span>
<span class="line"><span style="color:#A6ACCD;">watch 监听</span></span>
<span class="line"><span style="color:#A6ACCD;">filters 过滤器</span></span>
<span class="line"><span style="color:#A6ACCD;">mounted 挂载，生成</span></span>
<span class="line"><span style="color:#A6ACCD;">axios vue中的ajax</span></span>
<span class="line"><span style="color:#A6ACCD;">let 变量</span></span>
<span class="line"><span style="color:#A6ACCD;">const 常量</span></span></code></pre></div><h1 id="前端字符编码" tabindex="-1">前端字符编码 <a class="header-anchor" href="#前端字符编码" aria-label="Permalink to &quot;前端字符编码&quot;">​</a></h1><p>在开发过程中经常会遇到各种各样的编码，常见的有 UTF－8、Unicode、Base64 等，但前端世界远不止这三种编码，本文就来介绍前端常见的编码以及其使用方式。</p><h2 id="ascii" tabindex="-1">ASCII <a class="header-anchor" href="#ascii" aria-label="Permalink to &quot;ASCII&quot;">​</a></h2><p>我们知道，计算机只能理解二进制，二进制语言是面向机器的语言，直接来自计算机的指令系统，由 0 和 1 组成。它使用整数来编码数字（0-9）、大写字母（A-Z）、小写字母（A-Z）以及分号（；）、感叹号（！）等。例如，97 用于表示“a”，33用于表示“！”，这样就可以方便地存储在内存中。</p><p>互联网的早期只有英文字母，所以不需要担心任何其他字符，ASCII 就可以适用于这种情况的字符编码，例如 bits 对应的二进制如下：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">01100010 01101001 01110100 01110011</span></span>
<span class="line"><span style="color:#A6ACCD;">   b        i        t        s</span></span></code></pre></div><p>ASCII 全称为 American Standard Code for Information Interchange，即“美国信息交换标准代码”，是基于拉丁字母的一套电脑编码系统。ASCII 至今为止共定义了 128 个字符：</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/EO58xpw5UMP7j88v55Rtkg5yesQibtHwCxh0GuwlImdZKYDG6nE4lrJVxKMic2icrOaicRW8WPbhrV4TZSZ4cSxFLg/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>ASCII 可以分为两类：</p><ul><li><strong>可显示字符</strong>：编号范围是32-126（0x20-0x7E），共 95 个字符：</li></ul><p><img src="https://mmbiz.qpic.cn/mmbiz_png/EO58xpw5UMP7j88v55Rtkg5yesQibtHwCb3Kx63icQYOJUgAvcanec4yCpURyUuUAVW5iatnuk63lVPsVVQzJUQUg/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><ul><li><strong>控制字符</strong>：编号范围是0-31和127（0x00-0x1F和0x7F），共 33 个字符：</li></ul><p><img src="https://mmbiz.qpic.cn/mmbiz_png/EO58xpw5UMP7j88v55Rtkg5yesQibtHwCE9CU1TrMyic4HkUBEscMiaZUqYX08WvKIlVW0kAj3TkcQEbIYywAR6gw/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>可以看到，ASCII 码实际上是一种映射，是从二进制字符到字母数字字符的映射。所以当计算机收到以下二进制文件时：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">01001000 01100101 01101100 01101100 01101111 00100000 01110111 01101111 01110010 01101100 01100100</span></span></code></pre></div><p>使用 ASCII 码进行映射，上面的二进制编码可以翻译成“Hello world”。</p><p>“K” 在ASCII 中是75，可以将它转化为二进制，将 75 除以 2，然后继续，直到得到 0。如果除法不准确，则加 1 作为余数：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">75 / 2 = 37 + 1</span></span>
<span class="line"><span style="color:#A6ACCD;">37 / 2 = 18 + 1</span></span>
<span class="line"><span style="color:#A6ACCD;">18 / 2 =  9 + 0</span></span>
<span class="line"><span style="color:#A6ACCD;">9 / 2 =   4 + 1</span></span>
<span class="line"><span style="color:#A6ACCD;">4 / 2 =   2 + 0</span></span>
<span class="line"><span style="color:#A6ACCD;">2 / 2 =   1 + 0</span></span>
<span class="line"><span style="color:#A6ACCD;">1 / 2 =   0 + 1</span></span></code></pre></div><p>现在，提取“余数”并以相反的顺序放入它们：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">1101001 =&gt; 1001011</span></span></code></pre></div><p>因此，在 ASCII 中，“K”在二进制中被编码为 1001011。</p><p>ASCII 的主要缺点是它只能表示 256 个不同的字符，因为它只能使用 8 位。ASCII 不能用于对世界各地发现的许多类型的字符进行编码。但是如果想在计算机上使用中文、俄语、日语时，就需要一个不同的编码标准。Unicode 进一步扩展为 UTF-8、UTF-16、UTF-32以对各种类型的字符进行编码。因此，<strong>ASCII 和 Unicode 之间的主要区别就是用于编码的位数</strong>。下面就来看看 Unicode 的概念以及使用方式。</p><h2 id="unicode" tabindex="-1">Unicode <a class="header-anchor" href="#unicode" aria-label="Permalink to &quot;Unicode&quot;">​</a></h2><p>Unicode 是另一种字符编码，它仍然是：位查找 -&gt; 字符，由 Unicode Consortium 维护，其负责制定国际使用的软件标准。IT 行业将 Unicode 标准化以对计算机和其他电子和通信设备中的字符进行编码和表示。</p><p>Unicode 由许多代码点组成（将来自世界各地的大量字符映射到所有计算机都可以引用的键），代码点的集合称为字符集，这就是 Unicode。开发 Unicode 的目标是通过一种独特的方式将世界上任何语言的任何字符或符号转换成唯一的数字。可以在 unicode.org 上查找任何 Unicode 字符的编号，包括表情符号！</p><p>Unicode 看起来像这样：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">U+0048：拉丁文大写字母 H</span></span>
<span class="line"><span style="color:#A6ACCD;">U+0065：拉丁文小写字母 e</span></span>
<span class="line"><span style="color:#A6ACCD;">U+006C：拉丁文小写字母 l</span></span>
<span class="line"><span style="color:#A6ACCD;">U+006C：拉丁文小写字母 l</span></span>
<span class="line"><span style="color:#A6ACCD;">U+006F：拉丁文小写字母 o</span></span>
<span class="line"><span style="color:#A6ACCD;">U+0020：空格 [SP]</span></span>
<span class="line"><span style="color:#A6ACCD;">U+0057：拉丁文大写字母 W</span></span>
<span class="line"><span style="color:#A6ACCD;">U+006F：拉丁文小写字母 o</span></span>
<span class="line"><span style="color:#A6ACCD;">U+0072：拉丁文小写字母 r</span></span>
<span class="line"><span style="color:#A6ACCD;">U+006C：拉丁文小写字母 l</span></span>
<span class="line"><span style="color:#A6ACCD;">U+0064：拉丁文小写字母 d</span></span></code></pre></div><p>可以使用以下格式在 JavaScript 字符串中添加 unicode 序列 \uXXXX：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">const s1 = &#39;\u00E9&#39; //é</span></span></code></pre></div><p>可以通过组合两个 unicode 序列来创建一个序列：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">const s2 = &#39;\u0065\u0301&#39; //é</span></span></code></pre></div><p>虽然两个字符串的结果都是 é，但它们是两个不同的字符串，并且长度也不相同：</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/EO58xpw5UMP7j88v55Rtkg5yesQibtHwC20IJGI4ricIK4HwIUrL4ZeGA7w81AZxWMibibPT4rr1NwvER2BFtTDENg/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>ASCII 和 Unicode 是两种流行的编码方案。ASCII 编码符号、数字、字母等，而 Unicode 编码来自不同语言、字母、符号等的特殊文本，可以说 <strong>ASCII 是 Unicode 编码方案的一个子集</strong>。它们两个的区别如下：</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/EO58xpw5UMP7j88v55Rtkg5yesQibtHwCAyqP88SEdhhAB4kqzFQcOQWYwU5KgLdD5A3cgic8oib7frYSoULh8k8A/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><h2 id="utf-8、utf-16、utf-32" tabindex="-1">UTF-8、UTF-16、UTF-32 <a class="header-anchor" href="#utf-8、utf-16、utf-32" aria-label="Permalink to &quot;UTF-8、UTF-16、UTF-32&quot;">​</a></h2><h3 id="基本概念" tabindex="-1">基本概念 <a class="header-anchor" href="#基本概念" aria-label="Permalink to &quot;基本概念&quot;">​</a></h3><p><strong>UTF 是 Unicode 编码方式的一种</strong>。UTF 编码由 Unicode 标准定义，能够对需要的每个 Unicode 代码点进行编码。Unicode 编码方案根据用于对字符进行编码的位数进行分类。目前使用的 Unicode 编码方案有 UTF-7、UTF-8、UTF-16 和 UTF-32 ，分别使用 7 位、8 位、16 位和 32 位来表示字符。</p><p>那如何知道文件将使用哪种编码呢？有一种称为字节顺序标记(BOM，即 Byte Order Mark) 的东西，也称为编码签名。BOM是文件开头的一个两字节标记，用于标识文件是采用哪种格式的编码。</p><p>UTF-8 在互联网上使用最多，在 HTML5 中也被指定为文档的首选编码，所以下面将主要介绍 UTF-8。</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/EO58xpw5UMP7j88v55Rtkg5yesQibtHwC4FakB00mRFrBjrl1xYnKnjHML1Kgg0MLIs3dpUlicDtnq23xSZHccPw/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>UTF-8 将 0-127 的所有 Unicode 代码点编码为 1 个字节（与ASCII相同）。这意味着如果使用 ASCII 对程序进行编码，而用户使用 UTF-8，将不会有任何错误。1993年创建 UTF-8 时，很多数据都是 ASCII 格式的，所以通过兼容 UTF-8，在使用前不需要对数据进行转换。本质上，ASCII 格式的文件可以被视为 UTF-8 格式，而且可以正常工作。</p><h3 id="工作原理" tabindex="-1">工作原理 <a class="header-anchor" href="#工作原理" aria-label="Permalink to &quot;工作原理&quot;">​</a></h3><p>下面来详细看看 UTF-8 是如何工作的，以及为什么它会根据被编码的字符具有不同的长度。</p><p>UTF-8 以<strong>动态方式</strong>存储数字。Unicode 列表中的第一个占用 1 个字节，最后一个最多占用 4 个字节，如果处理的是英文文件，大多数字符可能只占用 1 个字节，与 ASCII 中的相同。<strong>这是通过用不同的字节数覆盖 Unicode 中的不同范围来实现的</strong>。</p><p>例如，要编码原始 ASCII 表中的字符（0-127），只需要 7 位，因为 27= 128。因此，可以将所有内容存储在 8 位的 1 字节中，并且仍然剩余一个空闲空间。而对于下一个范围（128-2047），就需要 11 bits，因为211＝2048，在 UTF-8 中就是 2 个字节。<img src="https://mmbiz.qpic.cn/mmbiz_png/EO58xpw5UMP7j88v55Rtkg5yesQibtHwCzvTIZoWdfHuKFWEKF0BXHsPT2ge8PqYoWbdwFYK3BdDuZCZenRWAsA/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片">计算机在读取 UTF-8 中以 0 开头的内容时，就知道只需要读取一个字节并显示 Unicode 中 0-127 范围内的正确字符即可。如果遇到两个 1，就需要读取 2 个字节，范围为128-2047，3 个 1 在一起表示需要读取三个字节。</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/EO58xpw5UMP7j88v55Rtkg5yesQibtHwCrFQW4EriasoPwae44eKYd8jecnjFhgHwc4CsKmVznKCaO1KkG1guB5Q/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><h3 id="utf-16、utf-32" tabindex="-1">UTF-16、UTF-32 <a class="header-anchor" href="#utf-16、utf-32" aria-label="Permalink to &quot;UTF-16、UTF-32&quot;">​</a></h3><p>世界范围内使用的大量字符是无法全部使用 8 位表示法进行编码，导致在 Unicode 编码下产生了 UTF-16 和 UTF-32 编码格式。在解释这些编码格式之前，先来看看平面的概念：</p><blockquote><p>Unicode 编码中有很多很多的字符，它并不是一次性定义的，而是分区进行定义的，每个区存放65536（216）个字符，这称为一个平面，目前总共有17 个平面。最前面的一个平面称为基本平面，它的码点从0 — 216-1，写成16进制就是U+0000 — U+FFFF，那剩下的16个平面就是辅助平面，码点范围是 U+10000—U+10FFFF。</p></blockquote><p>UTF-16 是 Unicode 编码集的一种编码形式，把 Unicode 字符集的抽象码位映射为16位长的整数（即码元）的序列，用于数据存储或传递。Unicode字符的码位需要1个或者2个16位长的码元来表示，因此UTF-16也是用变长字节表示的。</p><p><strong>UTF-16 编码规则：</strong></p><ul><li>编号在 U+0000—U+FFFF 的字符（常用字符集），直接用两个字节表示。</li><li>编号在 U+10000—U+10FFFF 之间的字符，需要用四个字节表示。</li></ul><p>那么问题来了，当遇到两个字节时，怎么知道是把它当做一个字符还是和后面的两个字节一起当做一个字符呢？</p><p>UTF-16 编码肯定也考虑到了这个问题，在基本平面内，从 U+D800 — U+DFFF 是一个空段，也就是说这个区间的码点不对应任何的字符，因此这些空段就可以用来映射辅助平面的字符。</p><p>辅助平面共有 220 个字符位，因此表示这些字符至少需要 20 个二进制位。UTF-16 将这 20 个二进制位分成两半，前 10 位映射在 U+D800 — U+DBFF，称为高位（H），后 10 位映射在 U+DC00 — U+DFFF，称为低位（L）。这就相当于，将一个辅助平面的字符拆成了两个基本平面的字符来表示。</p><p>因此，当我们遇到两个字节时，发现它的码点在 U+D800 —U+DBFF之间，就可以知道，它后面的两个字节的码点应该在 U+DC00 — U+DFFF 之间，这四个字节必须放在一起进行解读。</p><p>以 “<strong>𡠀</strong>” 字为例，它的 Unicode 码点为 0x21800，该码点超出了基本平面的范围，因此需要用四个字节来表示，步骤如下：</p><ul><li>首先计算超出部分的结果：0x21800 - 0x10000</li><li>将上面的计算结果转为20位的二进制数，不足20位就在前面补0，结果为：0001000110 0000000000</li><li>将得到的两个10位二进制数分别对应到两个区间中</li><li>U+D800 对应的二进制数为 1101100000000000， 将0001000110填充在它的后10 个二进制位，得到 1101100001000110，转成 16 进制数为 0xD846。同理，低位为 0xDC00，所以这个字的UTF-16 编码为 0xD846 0xDC00</li></ul><p>UTF-32 就是字符所对应编号的整数二进制形式，每个字符占四个字节，这个是直接进行转换的。该编码方式占用的储存空间较多，所以使用较少。比如“马” 字的 Unicode 编号是：U+9A6C，整数编号是39532，直接转化为二进制：1001 1010 0110 1100，这就是它的 UTF-32 编码。</p><h3 id="指定编码方式" tabindex="-1">指定编码方式 <a class="header-anchor" href="#指定编码方式" aria-label="Permalink to &quot;指定编码方式&quot;">​</a></h3><p>如果没有显式指定编码方式，浏览器假定任何程序的源代码都是用本地字符集编写的，这会因国家/地区而异，可能会出现意料之外的情况。因此，给 JavaScript 文档设置字符集非常重要。那该如何指定 UTF 编码呢？</p><p>如果使用 HTTP（或 HTTPS）获取文件，则 <code>Content-Type</code> 标头可以指定编码标准：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">Content-Type: application/javascript; charset=utf-8</span></span></code></pre></div><p>如果没有设置，可以检查 <code>script</code> 标签的 <code>charset</code> 属性：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">&lt;script src=&quot;./app.js&quot; charset=&quot;utf-8&quot;&gt;</span></span></code></pre></div><p>如果未设置，可以将它嵌入到 <code>&lt;head&gt;</code> 的顶部。</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">&lt;!DOCTYPE html&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">&lt;html lang=&quot;zh-CN&quot;&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">&lt;head&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">  &lt;meta charset=&quot;utf-8&quot;&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">&lt;/head&gt;</span></span></code></pre></div><p>注意，这两种情况下的 <code>charset</code> 属性都不区分大小。</p><p>虽然 JavaScript 源文件可以是任何类型的编码，但 JavaScript 会在执行之前在内部将其转换为 UTF-16。正如 ECMAScript 标准所说，JavaScript 字符串都是 UTF-16 序列：</p><blockquote><p>当 String 包含实际文本数据时，每个元素都被视为单个 UTF-16 代码单元。</p></blockquote><h2 id="base64" tabindex="-1">Base64 <a class="header-anchor" href="#base64" aria-label="Permalink to &quot;Base64&quot;">​</a></h2><h3 id="基本概念-1" tabindex="-1">基本概念 <a class="header-anchor" href="#基本概念-1" aria-label="Permalink to &quot;基本概念&quot;">​</a></h3><p>Base64 也称为 Base64 内容传输编码。Base64 是将二进制数据编码为 ASCII 文本。但它只使用了 64 个字符，再加上大多数字符集中存在的一个填充字符。所以它是一种仅使用可打印字符表示二进制数据的方法。Base64 常用于在通常处理文本数据的场景，表示、传输、存储一些二进制数据，包括MIME的电子邮件及XML的一些复杂数据。</p><p>Base64 编码用于通过不能正确处理二进制数据的介质传输数据。因此，对数据进行 Base64 编码以确保数据完整，无需通过此介质进行任何修改。base 64 编码结果形式如下：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">OWRjNGJjMDY5MzVmNGViMGExZTdkMzNjOGMwZTI3ZWI==</span></span></code></pre></div><h3 id="base64-编码" tabindex="-1">Base64 编码 <a class="header-anchor" href="#base64-编码" aria-label="Permalink to &quot;Base64 编码&quot;">​</a></h3><p>Base64 编码会将每 3 个字节的数据翻译成 4 个编码字符。它将从左到右开始扫描，然后选择代表 3 个字符的数据的前 3 个字节。这 3 个字节将是 24 位。现在它将把这 24 位分成四部分，每部分 6 位。然后每个 6 位组将在下表中进行索引以得到映射的字符：</p><img src="https://mmbiz.qpic.cn/mmbiz_png/EO58xpw5UMP7j88v55Rtkg5yesQibtHwCrI4OrpqXxqbalqt9IIicTIPuf5ZmAYjpeDyYpGY7t9ic6BDYVpRvPfcw/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片" style="zoom:50%;"><p>比如，有以下字符串：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">ab@</span></span></code></pre></div><p>它的位表示将是：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">a          b        @</span></span>
<span class="line"><span style="color:#A6ACCD;">01100001  01100010  01000000</span></span></code></pre></div><p>这些总共 24 位将被分为 4 组，每组 6 位：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">011000 010110 001001 000000</span></span></code></pre></div><p>它的数字表示为：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">24    22     9      0</span></span>
<span class="line"><span style="color:#A6ACCD;">011000 010110 001001 000000</span></span></code></pre></div><p>使用上面的数字索引到 base64 表中，映射结果如下：</p><ul><li>24 → Y</li><li>22 → W</li><li>9 → J</li><li>0 → A</li></ul><p>所以，这个字符串的base64编码就是：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">YWJA</span></span></code></pre></div><p>那如果输入的字符串不是 3 的倍数怎么办？这种情况下，就会使用填充字符<code>=</code>**。**假设字符串有 4 个字符</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">ab@c</span></span></code></pre></div><p>它的位表示将是：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">a          b        @        c</span></span>
<span class="line"><span style="color:#A6ACCD;">01100001  01100010  01000000 01100011</span></span></code></pre></div><p>前三个字节将组合在一起。最后的字节将用 4 个额外的 0 填充，以使总位可以被 6 整除：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">011000 010110 001001 000000 011000 110000</span></span>
<span class="line"><span style="color:#A6ACCD;">  24     22     9      0      24     48</span></span></code></pre></div><p>使用上面的数字索引到 base64 表中，映射结果如下：</p><ul><li>24 → Y</li><li>22 → W</li><li>9 → J</li><li>0 → A</li><li>24 → Y</li><li>48 → w</li></ul><p>结果如下：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">YWJAYw==</span></span></code></pre></div><p>这里，每两个额外的 0 由 = 字符表示。由于添加了 4 个额外的零，因此最后有两个 =。</p><h3 id="base64-解码" tabindex="-1">Base64 解码 <a class="header-anchor" href="#base64-解码" aria-label="Permalink to &quot;Base64 解码&quot;">​</a></h3><p>说完了 Base64 编码，下面来尝试将 base64 编码的字符串解码为原始字符串。以以下 Base64 字符串为例：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">YWJAY2Q=</span></span></code></pre></div><p>将其分组为 4 个字符一组：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">YWJA </span></span>
<span class="line"><span style="color:#A6ACCD;">Y2Q=</span></span></code></pre></div><p>现在从每个组中删除最后的 = 字符。对于剩余的字符串，将其转换为上表中相应的位表示形式。</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">Y      W       J      A     </span></span>
<span class="line"><span style="color:#A6ACCD;">011000 010110 001001 000000</span></span>
<span class="line"><span style="color:#A6ACCD;"></span></span>
<span class="line"><span style="color:#A6ACCD;">  Y      2      Q</span></span>
<span class="line"><span style="color:#A6ACCD;">011000 110110 010000</span></span></code></pre></div><p>现在将其分组为一组 8 位，保留尾随的 0：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">01100001  01100010  01000000 </span></span>
<span class="line"><span style="color:#A6ACCD;">01100011  01100100</span></span></code></pre></div><p>现在对于上面的每个字节，根据 ASCII 表分配字符：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">01100001  01100010  01000000</span></span>
<span class="line"><span style="color:#A6ACCD;">   a          b         @   </span></span>
<span class="line"><span style="color:#A6ACCD;"></span></span>
<span class="line"><span style="color:#A6ACCD;">01100011  01100100</span></span>
<span class="line"><span style="color:#A6ACCD;">   c          d</span></span></code></pre></div><p>因此最终的字符串就是：<strong>ab@cd</strong></p><h3 id="填充" tabindex="-1">填充 <a class="header-anchor" href="#填充" aria-label="Permalink to &quot;填充&quot;">​</a></h3><p>那为什么要将 Base64 编码后的字符串分成 4 个一组进行解码呢？就是因为填充<code>=</code>。填充 <code>=</code> 对于 base64 编码是否有必要呢，因为在解码时又丢弃了填充。主要考虑两种情况：</p><ul><li>发送单个字符的字符串时不需要填充；</li><li>发送多个字符的字符串的 base64 编码时，填充就很重要。如果连接未填充的字符串，则将无法获得原始字符串，因为有关添加的字节的信息将丢失。</li></ul><p>来看下面的例子：<img src="https://mmbiz.qpic.cn/mmbiz_png/EO58xpw5UMP7j88v55Rtkg5yesQibtHwCoZnGXV9n9Vq6jog4mkDtBFSjBjia85aIF2lzDrbROa4ib5YgicunWgBibg/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p><strong>当发送连接时没有填充，</strong> 合并的 Base64 字符串将是：YQYmMZGVm，尝试解码它时，会得到如下字符串，这是不正确的：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">a&amp;1</span></span></code></pre></div><p><strong>当使用填充发送连接时，</strong> 合并的 Base64 字符串将是：YQ==YmM=ZGVm，尝试解码它时，会得到以下字符串，这是正确的：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">abcdef</span></span></code></pre></div><p>所以，当传输多个字符时，填充是很有必要的。</p><p>因为基本上 Base64 在填充的情况下会将 3 个字节编码为 4 个 ASCII 字符。四个 ASCII 字符中的每一个都将作为 1 个字节通过网络发送。因此，最终的尺寸总是比原来的尺寸大 33.33%。因此，如果字符串的原始大小为 n 个字节，则经过 base64 编码后的大小将为：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">n * 4/3</span></span></code></pre></div><h2 id="javascript-编解码" tabindex="-1">JavaScript 编解码 <a class="header-anchor" href="#javascript-编解码" aria-label="Permalink to &quot;JavaScript 编解码&quot;">​</a></h2><p>最后来看看 JavaScript 中提供的关于编解码的方法。</p><h3 id="utf-8" tabindex="-1">UTF-8 <a class="header-anchor" href="#utf-8" aria-label="Permalink to &quot;UTF-8&quot;">​</a></h3><p>URL 只能包含标准的 ASCII 字符，所以必须对其他特殊字符进行编码。在 JavaScript 中，可以通过了以下方法对 URL 来做 UTF-8 编码与解码：</p><ul><li><code>encodeURI</code>、<code>decodeURI</code></li><li><code>encodeURIComponent</code>、<code>decodeURIComponent</code></li></ul><p>这里的编码指的就是将二进制数据转换为 ASCII 格式的方式，解码反之亦然，即将 ASCII 格式转换回原始内容。</p><p>那 <code>encodeURI</code> 和 <code>encodeURIComponent</code> 有什么区别呢？</p><ul><li>encodeURI 用于<strong>编码完整的 URL</strong>：</li></ul><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">encodeURI(&#39;https://domain.com/path to a document.pdf&#39;);</span></span>
<span class="line"><span style="color:#A6ACCD;"></span></span>
<span class="line"><span style="color:#A6ACCD;">// 结果：&#39;https://domain.com/path%20to%20a%20document.pdf&#39;</span></span></code></pre></div><ul><li><code>encodeURIComponent</code> 用于编码 URI 组件，例如查询字符串：</li></ul><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">`http://domain.com/?search=${encodeURIComponent(&#39;name=zhang san&amp;age=19&#39;)}`;</span></span>
<span class="line"><span style="color:#A6ACCD;"></span></span>
<span class="line"><span style="color:#A6ACCD;">// 结果：&#39;http://domain.com/?search=name%3Dzhang%20san%26age%3D19&#39;</span></span></code></pre></div><p>需要注意，有 11 个字符不能使用 <code>encodeURI</code> 编码，而需要使用 <code>encodeURIComponent</code> 进行编码：</p><p><img src="https://mmbiz.qpic.cn/mmbiz_png/EO58xpw5UMP7j88v55Rtkg5yesQibtHwCp7K7rkCnPk3xl3q5Y2yQWlFicrggRyauDcCToF5X9UHROf04qCICPaQ/640?wx_fmt=png&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" alt="图片"></p><p>另外，decodeURI 和 decodeURIComponent 是对分别由 encodeURI 和 encodeURIComponent 编码的字符串进行解码的方法。</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">decodeURI(&#39;https://domain.com/path%20to%20a%20document.pdf&#39;);</span></span>
<span class="line"><span style="color:#A6ACCD;"></span></span>
<span class="line"><span style="color:#A6ACCD;">// 结果：&#39;https://domain.com/path to a document.pdf&#39;</span></span>
<span class="line"><span style="color:#A6ACCD;"></span></span>
<span class="line"><span style="color:#A6ACCD;">`http://domain.com/?search=${decodeURIComponent(&#39;name%3Dzhang%20san%26age%3D19&#39;)}`;</span></span>
<span class="line"><span style="color:#A6ACCD;"></span></span>
<span class="line"><span style="color:#A6ACCD;">// 结果：&#39;http://domain.com/?search=name=zhang san&amp;age=19&#39;</span></span></code></pre></div><p>需要注意，<code>encodeURIComponent</code> 不编码 <code>- _ . ! ~ * &#39; ( )</code>。如果要对这些字符进行编码，则必须将它们替换为相应的 UTF-8 字符序列：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">const encode = (str) =&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">    encodeURIComponent(str)</span></span>
<span class="line"><span style="color:#A6ACCD;">        .replace(/\-/g, &#39;%2D&#39;)</span></span>
<span class="line"><span style="color:#A6ACCD;">        .replace(/\_/g, &#39;%5F&#39;)</span></span>
<span class="line"><span style="color:#A6ACCD;">        .replace(/\./g, &#39;%2E&#39;)</span></span>
<span class="line"><span style="color:#A6ACCD;">        .replace(/\!/g, &#39;%21&#39;)</span></span>
<span class="line"><span style="color:#A6ACCD;">        .replace(/\~/g, &#39;%7E&#39;)</span></span>
<span class="line"><span style="color:#A6ACCD;">        .replace(/\*/g, &#39;%2A&#39;)</span></span>
<span class="line"><span style="color:#A6ACCD;">        .replace(/\&#39;/g, &#39;%27&#39;)</span></span>
<span class="line"><span style="color:#A6ACCD;">        .replace(/\(/g, &#39;%28&#39;)</span></span>
<span class="line"><span style="color:#A6ACCD;">        .replace(/\)/g, &#39;%29&#39;);</span></span></code></pre></div><p>解码函数如下所示：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">const decode = (str) =&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">    decodeURIComponent(</span></span>
<span class="line"><span style="color:#A6ACCD;">        str</span></span>
<span class="line"><span style="color:#A6ACCD;">            .replace(/\\%2D/g, &#39;-&#39;)</span></span>
<span class="line"><span style="color:#A6ACCD;">            .replace(/\\%5F/g, &#39;_&#39;)</span></span>
<span class="line"><span style="color:#A6ACCD;">            .replace(/\\%2E/g, &#39;.&#39;)</span></span>
<span class="line"><span style="color:#A6ACCD;">            .replace(/\\%21/g, &#39;!&#39;)</span></span>
<span class="line"><span style="color:#A6ACCD;">            .replace(/\\%7E/g, &#39;~&#39;)</span></span>
<span class="line"><span style="color:#A6ACCD;">            .replace(/\\%2A/g, &#39;*&#39;)</span></span>
<span class="line"><span style="color:#A6ACCD;">            .replace(/\\%27/g, &quot;&#39;&quot;)</span></span>
<span class="line"><span style="color:#A6ACCD;">            .replace(/\\%28/g, &#39;(&#39;)</span></span>
<span class="line"><span style="color:#A6ACCD;">            .replace(/\\%29/g, &#39;)&#39;)</span></span>
<span class="line"><span style="color:#A6ACCD;">    );</span></span></code></pre></div><h3 id="base64-1" tabindex="-1">Base64 <a class="header-anchor" href="#base64-1" aria-label="Permalink to &quot;Base64&quot;">​</a></h3><p>在JavaScript 中，可以使用 <code>btoa()</code>（binary to ASCII）和 <code>atob()</code>（ASCII to binary）方法来做 Base64 的编码和解码。主要是用于 Data URIs。</p><p>下面来对字符串 HelloWorld 做 Base64 的编码与解码：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">const encodedData = btoa(&#39;HelloWorld&#39;); // &quot;SGVsbG9Xb3JsZA==&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">const decodedData = atob(encodedData); // &quot;HelloWorld&quot;</span></span></code></pre></div><p>由于ASCII 无法表示中文，因此要先做 UTF-8 编码，然后再做Base64 编码；解码方式为先做 Base64 解码，再做UTF-8 解码：</p><div class="language-"><button title="Copy Code" class="copy"></button><span class="lang"></span><pre class="shiki material-theme-palenight"><code><span class="line"><span style="color:#A6ACCD;">const encodedData = btoa(encodeURI(&#39;你好&#39;)); //  &quot;JUU0JUJEJUEwJUU1JUE1JUJE&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">const decodedData = decodeURI(atob(encodedData)); // &quot;你好&quot;</span></span></code></pre></div><h1 id="品牌设计趋势" tabindex="-1">品牌设计趋势 <a class="header-anchor" href="#品牌设计趋势" aria-label="Permalink to &quot;品牌设计趋势&quot;">​</a></h1><p>在品牌设计方面存在一个悖论。趋势一直在变化，但品牌必须保持不变，保留其本质、价值和形象。</p><p>一方面，品牌必须保持可识别性。另一方面，它不能过时。为了向全世界传播其信息，品牌必须说语言并满足其受众的期望。如果它不这样做，观众就会消失。一个品牌必须保持令人兴奋、易于理解、情感亲近和与时俱进。这就是为什么即使是最古老、最受尊敬的品牌也会顺应潮流、与时俱进。</p><p>趋势不是目标，而是达到目的的手段。</p><p>了解这一点的设计师将始终能够找到正确的方法，无论是创建新的视觉识别还是品牌重塑。</p><p>让我们来看看在 2021 年已经证明其价值并将在 2022 年自信地保持的网页设计趋势。所有这些都只是品牌交流所用视觉语言的特征。</p><p>新词和表达方式无时无刻不在出现，语音和发音变化，但语言的核心保持不变。同样的规则也适用于设计。有希望的趋势结合了新旧。通过吸收过去所能提供的最好的东西，他们将其带入未来。</p><p>那么，到 2022 年，品牌将携带什么？</p><h2 id="_1、极简主义" tabindex="-1">1、极简主义 <a class="header-anchor" href="#_1、极简主义" aria-label="Permalink to &quot;1、极简主义&quot;">​</a></h2><p>极简主义设计已不仅仅是一种简单的趋势。在一个充斥着信息和视觉效果的世界里，这是必不可少的。</p><p>在混乱中创造秩序，消除所有干扰，强调基本要素——所有这些对于品牌塑造至关重要。</p><p>简单的形状保证了更容易的感知、更好的记忆和更快的识别。简单和简洁集中精力和力量。</p><h2 id="_2、多彩极简主义" tabindex="-1">2、多彩极简主义 <a class="header-anchor" href="#_2、多彩极简主义" aria-label="Permalink to &quot;2、多彩极简主义&quot;">​</a></h2><p>具有有限调色板的传统极简主义正逐渐被新的、丰富多彩的变化所取代。它保留了清晰简洁的形状和含义，但通过鲜艳的色彩在视觉上更加丰富。从本质上讲，它是两种设计的融合，其中传统的组合被明亮的色彩和元素所增强。</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2023.3.30/202302211032622.png" alt="image-20230221103239143" style="zoom:50%;"><h2 id="_3、黑暗主题" tabindex="-1">3、黑暗主题 <a class="header-anchor" href="#_3、黑暗主题" aria-label="Permalink to &quot;3、黑暗主题&quot;">​</a></h2><p>应用程序、网站、社交媒体平台和操作系统越来越多地提供黑暗方案。它很受用户欢迎。</p><p>请注意，品牌设计在黑暗模式下看起来非常不同。熟悉的调色板可能不适用于黑色背景。为了达到与灯光方案相同的效果，需要调整颜色。一些品牌在意识形态上反对黑暗计划。但其余的可以利用其引人注目的效果：对比、生动活泼的亮点、深度印象、优雅和威望。</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2023.3.30/202302211032906.png" alt="image-20230221103225774" style="zoom:50%;"><h2 id="_4、几何设计" tabindex="-1">4、几何设计 <a class="header-anchor" href="#_4、几何设计" aria-label="Permalink to &quot;4、几何设计&quot;">​</a></h2><p>几何风格在创造视觉识别方面表现出真正的希望。它用精确的线条和简单的形状说话。</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2023.3.30/202302211032069.png" alt="image-20230221103208990" style="zoom:50%;"><p>几何设计同样适用于主要元素（例如徽标）和背景（装饰品、图案等）。元素可以无休止地组合和重新组合，以达到酷炫的效果和共同的视觉节奏。几何设计更容易坚持标志性风格。</p><h2 id="_5、柔和的颜色" tabindex="-1">5、柔和的颜色 <a class="header-anchor" href="#_5、柔和的颜色" aria-label="Permalink to &quot;5、柔和的颜色&quot;">​</a></h2><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2023.3.30/202302211031396.png" alt="image-20230221103154020" style="zoom:50%;"><p>柔和的色彩一如既往地流行。它们令人赏心悦目，令人放松，给人以宁静祥和的印象。薄荷色调使设计看起来清新干净。柔和的色调象征着舒适和安全。这正是一些企业所需要的。</p><p>紫色色调在 2021 年特别流行。它们与柔和的色彩相得益彰，营造出宁静的氛围，因此它们无处不在。</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2023.3.30/202302211031800.png" alt="image-20230221103138605" style="zoom:50%;"><h2 id="_6、-经典风格" tabindex="-1">6、 经典风格 <a class="header-anchor" href="#_6、-经典风格" aria-label="Permalink to &quot;6、 经典风格&quot;">​</a></h2><p>对于将自己定位为传统、稳定、地位和声望的守护者的公司来说，与经典风格永远相关。这些品牌更喜欢比例严格、形状精确和优雅简约的设计。经典标志是几何形状、字母组合和装饰品的令人印象深刻的组合。有时它代表公司的名称。</p><p>经典的衬线字体又回来了，并且经常与非经典风格相结合。这些字体唤起了怀旧的感觉和“良好的旧可靠性”，这解释了它们的复兴。</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2023.3.30/202302211031437.png" alt="image-20230221103120100" style="zoom:50%;"><h2 id="_7、自然设计" tabindex="-1">7、自然设计 <a class="header-anchor" href="#_7、自然设计" aria-label="Permalink to &quot;7、自然设计&quot;">​</a></h2><p>这种趋势不仅与自然、环境和健康有关；它关乎所有事物的自然性：自然的色彩、非舞台化的照片、品牌和人物的坦率真实故事。渐变也很受欢迎，因为它们使图像更加壮观和有效。</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2023.3.30/202302211031825.png" alt="image-20230221103108579" style="zoom:50%;"><h2 id="_8、插图" tabindex="-1">8、插图 <a class="header-anchor" href="#_8、插图" aria-label="Permalink to &quot;8、插图&quot;">​</a></h2><p>插图越来越多地进入品牌设计。它们吸引注意力，唤起积极的情绪，帮助与用户交流，并营造更轻松的氛围。这是讲述品牌故事的一种简单、高效且令人难忘的方式。插图使品牌独特、有趣且更人性化。</p><p>说明性图标和符号增加了真实性并增加了识别度。这是一个由来已久的趋势。耐克、苹果和星巴克几十年来一直在追随它，而且不会很快停止。</p><img src="https://edu-8673.oss-cn-beijing.aliyuncs.com/img2023.3.30/202302211030025.png" alt="image-20230221103052791" style="zoom:50%;"><h2 id="_9、动画标志" tabindex="-1">9、动画标志 <a class="header-anchor" href="#_9、动画标志" aria-label="Permalink to &quot;9、动画标志&quot;">​</a></h2><p>拥有一个动画标志越来越成为一种必需品，而不是一种趋势。像这样的标志会立即吸引观众的注意力并保留一段时间，这对于记忆至关重要。动画徽标在移动设备上看起来不错。具有动画图形的页面可以更快地吸引观众。</p><p>动画可用于通过扩展静态徽标中包含的想法来讲述品牌故事。只需几秒钟，您就可以展示品牌的活动、工作原则，甚至价值观。成功的例子有 LinkedIn 和 FedEx。</p></div></div></main><footer class="VPDocFooter" data-v-6b87e69f data-v-37656e44><!--[--><!--]--><!----><nav class="prev-next" data-v-37656e44><div class="pager" data-v-37656e44><!----></div><div class="pager" data-v-37656e44><a class="pager-link next" href="/notebook/Java/Java%E5%9F%BA%E7%A1%80.html" data-v-37656e44><span class="desc" data-v-37656e44>Next page</span><span class="title" data-v-37656e44>Java基础</span></a></div></nav></footer><!--[--><!--]--></div></div></div><!--[--><!--]--></div></div><!----><!--[--><!--]--></div></div>
    <script>window.__VP_HASH_MAP__=JSON.parse("{\"2、数据库_mysql_mysql面试_基础.md\":\"40da680a\",\"1、学前端_5、小程序_小程序项目.md\":\"60a1629b\",\"1、学前端_4、node_知识篇.md\":\"a7fb500e\",\"1、学前端_2、js_ts_es6 进阶.md\":\"6d07ba10\",\"1、学前端_3、vue_vue3_vue3进阶.md\":\"7ac622b4\",\"5、运维_jenkins.md\":\"929081f8\",\"1、学前端_2、js_ts_typescript.md\":\"875a4aa4\",\"2、数据库_mysql_mysql核心_设计.md\":\"7faf46d1\",\"2、数据库_mysql_mysql核心_基础.md\":\"d8e97f3e\",\"1、学前端_1、html_css_html基础.md\":\"7584d076\",\"1、学前端_5、专题篇_问题篇.md\":\"e893aaa2\",\"2、数据库_mysql_mysql面试_进阶.md\":\"f934806d\",\"3、springboot_运维_原理.md\":\"f4a39db6\",\"2、数据库_influxdb.md\":\"6e1711e1\",\"3、springboot_新特性.md\":\"cdf3e307\",\"mybatis_mybatisplus_jpa.md\":\"8e41681b\",\"1、学前端_5、小程序_小程序优化.md\":\"a2185198\",\"2、数据库_redis_redis基础.md\":\"856df0e0\",\"linux_实用脚本.md\":\"f2299dd5\",\"4、微服务_必备_分布式基础.md\":\"d49863d5\",\"2、数据库_redis_redis优化.md\":\"e66ae32f\",\"4、微服务_springsecurity_进阶篇.md\":\"235a8e9e\",\"5、运维_chatgpt.md\":\"10db3823\",\"2、数据库_mysql_分库分表.md\":\"e1c8a095\",\"start.md\":\"9bc1ff8d\",\"5、运维_github.md\":\"2ec6c735\",\"java学前端_css.md\":\"f11b47f0\",\"1、学前端_5、专题篇_知识篇.md\":\"a463ed8d\",\"linux_软件部署.md\":\"d6722925\",\"2、数据库_neo4j.md\":\"97ad22ac\",\"team.md\":\"ce467a6a\",\"nginx_实战篇.md\":\"7785486e\",\"index.md\":\"8c3ec167\",\"计算机基础_计算机网络_网络基础.md\":\"7a54a85d\",\"1、学前端_4、node_进阶篇.md\":\"60f6db69\",\"java_java集合.md\":\"a049b313\",\"1、学前端_3、vue_vue3_vue3高级.md\":\"614d1516\",\"1、学前端_5、小程序_微信小程序.md\":\"9a4be771\",\"5、运维_netty.md\":\"12ca0278\",\"2、数据库_mysql_mysql核心_运维.md\":\"83f97c16\",\"idea_vs code.md\":\"afdcb593\",\"java学前端_vue3_组件.md\":\"1086884e\",\"idea_chrome.md\":\"4a32afbc\",\"云原生_k8s.md\":\"db58e65a\",\"2、数据库_mysql_mysql核心_进阶.md\":\"61d16dff\",\"ssm_springbatch.md\":\"f799ab4a\",\"三高_分布式.md\":\"db1b8a1b\",\"2、数据库_elasticsearch_1、es基础.md\":\"04d17448\",\"linux_linux基础.md\":\"4b0bf394\",\"idea_idea插件.md\":\"fa86e45a\",\"可视化 _ 监控_可视化大屏.md\":\"004553bd\",\"2、数据库_mongodb_整合.md\":\"3c47d7f4\",\"4、微服务_springsecurity_基础篇.md\":\"534a3401\",\"4、微服务_进阶.md\":\"69095c58\",\"计算机基础_计算机基础_操作系统.md\":\"0f75d113\",\"可视化 _ 监控_zabbix.md\":\"71f2270e\",\"nginx_基础篇.md\":\"c7d8bb50\",\"1、学前端_4、node_项目实战.md\":\"bc5065b8\",\"2、数据库_redis_redis原理.md\":\"5cedf685\",\"可视化 _ 监控_监控基础.md\":\"ac56ce4d\",\"三高_高并发.md\":\"ea9ffc99\",\"2、数据库_redis_redis高级.md\":\"1d5872f6\",\"1、学前端_4、node_基础篇.md\":\"581cc13a\",\"2、数据库_mongodb_基础.md\":\"fb7a0a29\",\"idea_idea基础.md\":\"6f2f9638\",\"4、微服务_必备_sentinel.md\":\"2edfbf6c\",\"2、数据库_elasticsearch_3、es高级.md\":\"ef146606\",\"1、学前端_3、vue_vue3_vue3新语法.md\":\"8afd5409\",\"消息中间件_canal.md\":\"3949163c\",\"ssm_maven.md\":\"2c5e12ed\",\"4、微服务_springsecurity_高级篇.md\":\"882d3ff3\",\"linux_linux进阶.md\":\"188ef7b4\",\"计算机基础_设计模式_uml.md\":\"634ba256\",\"计算机基础_算法_leetcode.md\":\"77162fb9\",\"项目实战_小兔鲜_进阶篇1.md\":\"17c52c81\",\"1、学前端_2、js_ts_es6 基础.md\":\"fda3f18b\",\"项目实战_小兔鲜_进阶篇2.md\":\"a0f23006\",\"软件测试_测试基础.md\":\"8c1060cd\",\"2、数据库_redis_本地缓存.md\":\"00617fe6\",\"nginx_面试篇.md\":\"e3fb373a\",\"mybatis_mybatisplus_mybatis.md\":\"9239e0ad\",\"linux_shell.md\":\"ae53d83b\",\"2、数据库_mysql_mysql核心_优化.md\":\"36230425\",\"项目实战_项目推荐.md\":\"f9d97630\",\"mybatis_mybatisplus_mybatisplus.md\":\"0030fd35\",\"项目实战_百度地图_进阶篇.md\":\"c8b93267\",\"三高_高可用.md\":\"323840c5\",\"java_java新特性.md\":\"22abf56d\",\"软件测试_压力测试.md\":\"9ab44440\",\"java学前端_html_js.md\":\"e0fcd240\",\"2、数据库_redis_redis实战.md\":\"d6daeeab\",\"nginx_进阶篇.md\":\"e6b63195\",\"三高_秒杀.md\":\"3878bb64\",\"5、运维_git.md\":\"0264925c\",\"java_java进阶.md\":\"e79cb5b4\",\"并发 _ 多线程_基础篇.md\":\"7adbfac5\",\"项目实战_百度地图_基础篇.md\":\"8afa5954\",\"java学前端_react.md\":\"3ec827dd\",\"1、学前端_1、html_css_css基础.md\":\"01b56712\",\"项目实战_小兔鲜_基础篇.md\":\"646f5df5\",\"1、学前端_2、js_ts_js 基础.md\":\"cb13e36f\",\"可视化 _ 监控_监控进阶.md\":\"0cdbc292\",\"计算机基础_设计模式_基础篇.md\":\"51617287\",\"计算机基础_数据结构_基础篇.md\":\"b2bfd8d4\",\"项目实战_苍穹外卖_进阶篇.md\":\"48415e41\",\"ssm_spring.md\":\"ab514659\",\"消息中间件_rabbitmq.md\":\"45b1eb28\",\"1、学前端_1、html_css_网页进阶.md\":\"db998248\",\"消息中间件_kafka.md\":\"b747dabf\",\"云原生_docker.md\":\"983c7ba7\",\"4、微服务_必备_分布式锁.md\":\"5af1cf8d\",\"消息中间件_rocketmq.md\":\"d441da85\",\"项目实战_黑马头条_基础篇.md\":\"b05af3a6\",\"ssm_springmvc.md\":\"81b9714f\",\"项目实战_支付.md\":\"1d7407dd\",\"项目实战_黑马头条_进阶篇2.md\":\"bff0015b\",\"项目实战_黑马头条_进阶篇.md\":\"19f18388\",\"java学前端_vue2_组件.md\":\"58c6b1df\",\"3、springboot_基础篇.md\":\"529c66f4\",\"3、springboot_应用篇.md\":\"8b92aa61\",\"项目实战_黑马头条_高级篇.md\":\"227c08c1\",\"1、学前端_5、小程序_uniapp.md\":\"71a282b4\",\"项目实战_云尚办公_基础篇.md\":\"1fe188ba\",\"并发 _ 多线程_并发完善.md\":\"26619c46\",\"1、学前端_2、js_ts_js 进阶.md\":\"657dfb8f\",\"java_java高级.md\":\"23782d1a\",\"java_java基础.md\":\"86d67c77\"}");window.__VP_SITE_DATA__=JSON.parse("{\"lang\":\"en-US\",\"dir\":\"ltr\",\"title\":\"VitePress\",\"description\":\"A VitePress site\",\"base\":\"/notebook/\",\"head\":[],\"appearance\":true,\"themeConfig\":{\"algolia\":{\"appId\":\"DW7O63I9IR\",\"apiKey\":\"f8ed758cdb288a8b06542bc35923c1a1\",\"indexName\":\"notebook\"},\"sidebar\":[{\"text\":\"Java\",\"collapsed\":true,\"items\":[{\"text\":\"Java基础\",\"link\":\"/Java/Java基础\"},{\"text\":\"Java新特性\",\"link\":\"/Java/Java新特性\"},{\"text\":\"Java进阶\",\"link\":\"/Java/Java进阶\"},{\"text\":\"Java集合\",\"link\":\"/Java/Java集合\"},{\"text\":\"Java高级\",\"link\":\"/Java/Java高级\"}]},{\"text\":\"Linux\",\"collapsed\":true,\"items\":[{\"text\":\"Linux基础\",\"link\":\"/Linux/Linux基础\"},{\"text\":\"Linux新特性\",\"link\":\"/Linux/Linux进阶\"},{\"text\":\"Shell脚本\",\"link\":\"/Linux/Shell\"},{\"text\":\"实用脚本\",\"link\":\"/Linux/实用脚本\"},{\"text\":\"软件部署\",\"link\":\"/Linux/软件部署\"}]},{\"text\":\"Nginx\",\"collapsed\":true,\"items\":[{\"text\":\"基础篇\",\"link\":\"/Nginx/基础篇\"},{\"text\":\"进阶篇\",\"link\":\"/Nginx/进阶篇\"},{\"text\":\"实战篇\",\"link\":\"/Nginx/实战篇\"},{\"text\":\"面试篇\",\"link\":\"/Nginx/面试篇\"}]},{\"text\":\"SSM\",\"collapsed\":true,\"items\":[{\"text\":\"Maven\",\"link\":\"/SSM/Maven\"},{\"text\":\"Spring\",\"link\":\"/SSM/Spring\"},{\"text\":\"SpringMVC\",\"link\":\"/SSM/SpringMVC\"},{\"text\":\"SpringBatch\",\"link\":\"/SSM/SpringBatch\"}]},{\"text\":\"SpringBoot\",\"collapsed\":true,\"items\":[{\"text\":\"基础篇\",\"link\":\"/3、SpringBoot/基础篇\"},{\"text\":\"应用篇\",\"link\":\"/3、SpringBoot/应用篇\"},{\"text\":\"新特性\",\"link\":\"/3、SpringBoot/新特性\"},{\"text\":\"运维&原理\",\"link\":\"/3、SpringBoot/运维&原理\"}]},{\"text\":\"SpringCloud\",\"collapsed\":true,\"items\":[{\"text\":\"SpringCloud\",\"link\":\"/4、微服务/进阶\"},{\"text\":\"Sentinel\",\"link\":\"/4、微服务/必备/Sentinel\"}]},{\"text\":\"SpringSecurity\",\"collapsed\":true,\"items\":[{\"text\":\"SpringSecurity基础篇\",\"link\":\"/4、微服务/SpringSecurity/基础篇\"},{\"text\":\"SpringSecurity进阶篇\",\"link\":\"/4、微服务/SpringSecurity/进阶篇\"},{\"text\":\"SpringSecurity高级篇\",\"link\":\"/4、微服务/SpringSecurity/高级篇\"}]},{\"text\":\"Mybatis & MybatisPlus\",\"collapsed\":true,\"items\":[{\"text\":\"Mybatis\",\"link\":\"/Mybatis&MybatisPlus/Mybatis\"},{\"text\":\"MybatisPlus\",\"link\":\"/Mybatis&MybatisPlus/MybatisPlus\"},{\"text\":\"JPA\",\"link\":\"/Mybatis&MybatisPlus/JPA\"}]},{\"text\":\"Git & ChatGPT\",\"collapsed\":true,\"items\":[{\"text\":\"Git\",\"link\":\"/5、运维/Git\"},{\"text\":\"Github\",\"link\":\"/5、运维/Github\"},{\"text\":\"ChatGPT\",\"link\":\"/5、运维/ChatGPT\"},{\"text\":\"Jenkins\",\"link\":\"/5、运维/Jenkins\"},{\"text\":\"Netty\",\"link\":\"/5、运维/Netty\"}]},{\"text\":\"数据库\",\"collapsed\":true,\"items\":[{\"text\":\"MySQL\",\"collapsed\":true,\"items\":[{\"text\":\"MySQL基础\",\"link\":\"/2、数据库/MySQL/MySQL核心/基础\"},{\"text\":\"MySQL进阶\",\"link\":\"/2、数据库/MySQL/MySQL核心/进阶\"},{\"text\":\"MySQL优化\",\"link\":\"/2、数据库/MySQL/MySQL核心/优化\"},{\"text\":\"MySQL设计\",\"link\":\"/2、数据库/MySQL/MySQL核心/设计\"},{\"text\":\"MySQL运维\",\"link\":\"/2、数据库/MySQL/MySQL核心/运维\"},{\"text\":\"分库分表\",\"link\":\"/2、数据库/MySQL/分库分表\"}]},{\"text\":\"Redis\",\"collapsed\":true,\"items\":[{\"text\":\"Redis基础\",\"link\":\"/2、数据库/Redis/Redis基础\"},{\"text\":\"Redis优化\",\"link\":\"/2、数据库/Redis/Redis优化\"},{\"text\":\"Redis原理\",\"link\":\"/2、数据库/Redis/Redis原理\"},{\"text\":\"Redis高级\",\"link\":\"/2、数据库/Redis/Redis高级\"},{\"text\":\"Redis实战\",\"link\":\"/2、数据库/Redis/Redis实战\"},{\"text\":\"本地缓存\",\"link\":\"/2、数据库/Redis/本地缓存\"}]},{\"text\":\"MongoDB\",\"collapsed\":true,\"items\":[{\"text\":\"MongoDB基础\",\"link\":\"/2、数据库/MongoDB/基础\"},{\"text\":\"MongoDB进阶\",\"link\":\"/2、数据库/MongoDB/整合\"}]},{\"text\":\"ElasticSearch\",\"collapsed\":true,\"items\":[{\"text\":\"ES基础\",\"link\":\"/2、数据库/ElasticSearch/1、ES基础\"},{\"text\":\"ES高级\",\"link\":\"/2、数据库/ElasticSearch/3、ES高级\"}]},{\"text\":\"InfluxDB\",\"link\":\"/2、数据库/influxdb\"},{\"text\":\"Neo4j\",\"link\":\"/2、数据库/Neo4j\"}]},{\"text\":\"高并发 & 秒杀 & 分布式\",\"collapsed\":true,\"items\":[{\"text\":\"分布式理论\",\"link\":\"/三高/分布式\"},{\"text\":\"分布式锁\",\"link\":\"/4、微服务/必备/分布式锁\"},{\"text\":\"秒杀\",\"link\":\"/三高/秒杀\"},{\"text\":\"高可用\",\"link\":\"/三高/高可用\"},{\"text\":\"高并发\",\"link\":\"/三高/高并发\"}]},{\"text\":\"云原生\",\"collapsed\":true,\"items\":[{\"text\":\"Docker\",\"link\":\"/云原生/Docker\"},{\"text\":\"K8S\",\"link\":\"/云原生/K8S\"}]},{\"text\":\"可视化 & 监控\",\"collapsed\":true,\"items\":[{\"text\":\"监控基础\",\"link\":\"/可视化 & 监控/监控基础\"},{\"text\":\"监控进阶\",\"link\":\"/可视化 & 监控/监控进阶\"},{\"text\":\"可视化大屏\",\"link\":\"/可视化 & 监控/可视化大屏\"},{\"text\":\"Zabbix\",\"link\":\"/可视化 & 监控/Zabbix\"}]},{\"text\":\"学前端\",\"collapsed\":true,\"items\":[{\"text\":\"HTML+CSS\",\"collapsed\":true,\"items\":[{\"text\":\"HTML基础\",\"link\":\"/1、学前端/1、HTML+CSS/HTML基础\"},{\"text\":\"CSS基础\",\"link\":\"/1、学前端/1、HTML+CSS/CSS基础\"},{\"text\":\"网页进阶\",\"link\":\"/1、学前端/1、HTML+CSS/网页进阶\"}]},{\"text\":\"JS+TS\",\"collapsed\":true,\"items\":[{\"text\":\"JS基础\",\"link\":\"/1、学前端/2、JS+TS/JS 基础\"},{\"text\":\"JS进阶\",\"link\":\"/1、学前端/2、JS+TS/JS 进阶\"},{\"text\":\"ES6基础\",\"link\":\"/1、学前端/2、JS+TS/ES6 基础\"},{\"text\":\"ES6进阶\",\"link\":\"/1、学前端/2、JS+TS/ES6 进阶\"},{\"text\":\"TS基础\",\"link\":\"/1、学前端/2、JS+TS/TypeScript\"}]},{\"text\":\"NodeJS\",\"collapsed\":true,\"items\":[{\"text\":\"Node基础\",\"link\":\"/1、学前端/4、Node/基础篇\"},{\"text\":\"Node进阶\",\"link\":\"/1、学前端/4、Node/进阶篇\"},{\"text\":\"项目实战\",\"link\":\"/1、学前端/4、Node/项目实战\"}]},{\"text\":\"Vue\",\"collapsed\":true,\"items\":[{\"text\":\"Vue3进阶\",\"link\":\"/1、学前端/3、Vue/Vue3/Vue3进阶\"},{\"text\":\"Vue3高级\",\"link\":\"/1、学前端/3、Vue/Vue3/Vue3高级\"},{\"text\":\"Vue3新语法\",\"link\":\"/1、学前端/3、Vue/Vue3/Vue3新语法\"},{\"text\":\"项目实战\",\"link\":\"/1、学前端/3、Vue/Vue2/Vue2项目\"}]},{\"text\":\"小程序\",\"collapsed\":true,\"items\":[{\"text\":\"小程序基础\",\"link\":\"/1、学前端/5、小程序/微信小程序\"},{\"text\":\"小程序优化\",\"link\":\"/1、学前端/5、小程序/小程序优化\"},{\"text\":\"uniapp\",\"link\":\"/1、学前端/5、小程序/uniapp\"},{\"text\":\"项目实战\",\"link\":\"/1、学前端/5、小程序/小程序项目\"}]}]},{\"text\":\"计算机基础\",\"collapsed\":true,\"items\":[{\"text\":\"数据结构\",\"link\":\"/计算机基础/数据结构/基础篇\"},{\"text\":\"操作系统\",\"link\":\"/计算机基础/计算机基础/操作系统\"},{\"text\":\"设计模式\",\"link\":\"/计算机基础/设计模式/基础篇\"},{\"text\":\"计算机网络\",\"link\":\"/计算机基础/计算机网络/网络基础\"},{\"text\":\"UML\",\"link\":\"/计算机基础/设计模式/UML\"},{\"text\":\"LeetCode\",\"link\":\"/计算机基础/算法/LeetCode\"}]},{\"text\":\"项目实战\",\"collapsed\":true,\"items\":[{\"text\":\"云尚办公\",\"collapsed\":true,\"items\":[{\"text\":\"基础篇\",\"link\":\"/项目实战/云尚办公/基础篇\"}]},{\"text\":\"小兔鲜\",\"collapsed\":true,\"items\":[{\"text\":\"基础篇\",\"link\":\"/项目实战/小兔鲜/基础篇\"},{\"text\":\"进阶篇1\",\"link\":\"/项目实战/小兔鲜/进阶篇1\"},{\"text\":\"进阶篇2\",\"link\":\"/项目实战/小兔鲜/进阶篇2\"}]},{\"text\":\"地图\",\"collapsed\":true,\"items\":[{\"text\":\"基础篇\",\"link\":\"/项目实战/百度地图/基础篇\"},{\"text\":\"进阶篇\",\"link\":\"/项目实战/百度地图/进阶篇\"}]},{\"text\":\"苍穹外卖\",\"collapsed\":true,\"items\":[{\"text\":\"进阶篇\",\"link\":\"/项目实战/苍穹外卖/进阶篇\"}]},{\"text\":\"黑马头条\",\"collapsed\":true,\"items\":[{\"text\":\"基础篇\",\"link\":\"/项目实战/黑马头条/基础篇\"},{\"text\":\"进阶篇\",\"link\":\"/项目实战/黑马头条/进阶篇\"},{\"text\":\"进阶篇2\",\"link\":\"/项目实战/黑马头条/进阶篇2\"},{\"text\":\"高级篇\",\"link\":\"/项目实战/黑马头条/高级篇\"}]},{\"text\":\"支付\",\"link\":\"/项目实战/支付\"},{\"text\":\"项目推荐\",\"link\":\"/项目实战/项目推荐\"}]},{\"text\":\"团队成员\",\"link\":\"/team\"}],\"siteTitle\":\"任硕的文档\",\"logo\":\"/Vue.png\",\"nav\":[{\"text\":\"Java学前端\",\"items\":[{\"items\":[{\"text\":\"HTML+JS\",\"link\":\"/Java学前端/HTML+JS\"},{\"text\":\"CSS\",\"link\":\"/Java学前端/CSS\"},{\"text\":\"Vue2+组件\",\"link\":\"/Java学前端/Vue2+组件\"},{\"text\":\"Vue3+组件\",\"link\":\"/Java学前端/Vue3+组件\"},{\"text\":\"React\",\"link\":\"/Java学前端/React\"}]}],\"activeMatch\":\"/Java/\"},{\"text\":\"软件测试\",\"items\":[{\"items\":[{\"text\":\"测试基础\",\"link\":\"/软件测试/测试基础\"},{\"text\":\"压力测试\",\"link\":\"/软件测试/压力测试\"}]}]},{\"text\":\"多线程\",\"items\":[{\"items\":[{\"text\":\"基础篇\",\"link\":\"/并发 & 多线程/基础篇\"},{\"text\":\"进阶篇\",\"link\":\"/并发 & 多线程/并发完善\"}]}]},{\"text\":\"开发工具\",\"items\":[{\"items\":[{\"text\":\"Chrome\",\"link\":\"/IDEA/Chrome\"},{\"text\":\"IDEA基础\",\"link\":\"/IDEA/IDEA基础\"},{\"text\":\"IDEA插件\",\"link\":\"/IDEA/IDEA插件\"},{\"text\":\"VS Code\",\"link\":\"/IDEA/VS Code\"}]}]},{\"text\":\"消息中间件\",\"items\":[{\"items\":[{\"text\":\"RabbitMQ\",\"link\":\"/消息中间件/RabbitMQ\"},{\"text\":\"RocketMQ\",\"link\":\"/消息中间件/RocketMQ\"},{\"text\":\"Kafka\",\"link\":\"/消息中间件/Kafka\"},{\"text\":\"Canal\",\"link\":\"/消息中间件/Canal\"}]}]}],\"socialLinks\":[{\"icon\":\"github\",\"link\":\"https://github.com/renshuo123/renshuo123.github.io\"},{\"icon\":\"twitter\",\"link\":\"#\"},{\"icon\":{\"svg\":\"<svg t=\\\"1676028692954\\\" class=\\\"icon\\\" ...</path></svg>\"},\"link\":\"https://github.com/\"}]},\"locales\":{},\"scrollOffset\":90,\"cleanUrls\":false}");</script>
    
  </body>
</html>